28 May 2014

CSS Transition helper

for sass with compass

This is a component from an old project from mine, it’s a switcher, very small but have lots of transition.Transition is easy, but there are some details like:

Different durations

a
  +transition( background .5s, color .5s, text-indent 1s, letter-spacing 1s )

Different delay

a
  +transition( background .5s, color .3s .5s, font-size .5s .8s )

And, sometimes you may like it all delay .5s only when mouseout

a
  +transition( color .5s .5s, background 1s .5s )
  &:hover
    +transition( color .5s, background 1s )

Thanks to compass, it can be simpler

$delay: .5s
a
  +transition( color .5s, background 1s )
  +transition-delay( $delay )
  &:hover
    +transition( color .5s, background 1s )

See the Pen ymDls by naiting (@sliiice) on CodePen.

28 May 2014

Shadow in text

because flat design is not mandatory

We can use inset in the box-shadow property, but not in text-shadow. So we can trick this by using this following style (sass-flavor).

$bgcolor: sameasbackgroundcolor
.text
  color: rgba(#b5bc67, 0.8)
  text-shadow: 1px 3px 3px $bgcolor, 0 0 0 #000, 1px 3px 3px $bgcolor
  &::selection
    background: #5af
    text-shadow: none
    color: #fff

The first and last 1px 3px 3px $bgcolor control the shadow range, and I add a selection style to avoid it looks weird when select this text.

Live demo:

See the Pen mHwfL by Oliver - Frontend Developer (@Oliverl) on CodePen.

27 May 2014

Run rails post in console

for debug or restoring data

Today I learn a trick to mimic a webhook in console.

Before when I want to test out why the webhook send to OA is not working I have to actually trigger the webhook in other app, like KB. Moreover, it is sometimes hard to make the params identical with the original request.

We can solve this by using the console and the app object:

rails c
  Loading development environment (Rails 4.1.1)
  [1] pry(main)> params = { something: "somewhere" }
  [2] pry(main)> url = '/some/path'
  [3] pry(main)> app.post(url, params)

First I dig through the production log to get the params of the webhook. Then I issue app.post and that’s it! The app get a identical webhook as the log show. No more clicking UI!

27 May 2014

Gem reverse dependencies

who uses who

I have been looking for a way to see what gem uses a gem, so I can see examples of integration in other projects. The rubygems API guide don’t tell anything about such reverse dependency query. But it is actually there, it got merged some time ago, and optimized, but it is not documented yet (it runs really fast, kudos Rubygems guys).

ruby -ropen-uri -rpp -ryaml \
     -e 'pp YAML.load(open("https://rubygems.org/api/v1/gems/rails_best_practices/reverse_dependencies.yaml"))'

["metric_fu",
 "flyerhzm-metric_fu",
 "edouard-metric_fu",
 "devver-metric_fu",
 "goldstar-metric_fu",
 "socializer",
 "trollface",
 "guard-rails_best_practices",
 "rferraz-metric_fu",
 "git-hooks-helper",
 "odor",
 "rake_check",
 "koality",
 "danmayer-metric_fu",
 "bf4-metric_fu",
 "metrics_satellite",
 "code_hunter",
 "kinit",
 "rails-audit",
 "pronto-rails_best_practices",
 "free_disk_space",
 "warder",
 "ruby_osx_app",
 "sanelint"]

Out of curiosity I counted some wellknown gems usages by adding a .count at the end:

rake:    23766
rails:   6283
thor:    2786
pry:     2870
sinatra: 1964
devise:  422
24 May 2014

Recover mysql data

from dumps

Here is some tips from Roman. Broken data recovery is a common thing to do these days, either because users delete their stuff by accident, or the code breaks and writes wrong data to the system. We can classify all recovery tasks as:

  1. A full DB row recovery, usually happens when records are deleted by mistake.
  2. An attribute recovery, when only some attributes of a record are broken.

The first case is easier than the second. To recover full rows, we open the appropriate DB dump in Sequel Pro, prepare a query to select the rows which need to be recovered in the current DB, and then copy them as SQL INSERT, which is a nice and useful context menu option in that tool. The result should be run on production DB, and the recovery is done.

The second case requires writing some SQL to prepare the recovery statements. The magic looks like this:

SELECT CONCAT('update users set homeroom_advisor_id = ', homeroom_advisor_id, ' where id = ', id, ';') FROM users WHERE id in (3443,4332,5523)

This yields

update users set homeroom_advisor_id = 4673 where id = 3443;
update users set homeroom_advisor_id = 4380 where id = 4332;
update users set homeroom_advisor_id = 4616 where id = 5523;

which is nice, but what if somebody updated the advisor ID from NULL to something other meanwhile? We need to add the check:

SELECT CONCAT('update users set homeroom_advisor_id = ', homeroom_advisor_id, ' where id = ', id, ' and homeroom_advisor_id is null;') FROM users WHERE id in (3443,4332,5523)

The result:

update users set homeroom_advisor_id = 4673 where id = 3443 and homeroom_advisor_id is null;
update users set homeroom_advisor_id = 4380 where id = 4332 and homeroom_advisor_id is null;
update users set homeroom_advisor_id = 4616 where id = 5523 and homeroom_advisor_id is null;

is the query which can be used to restore the wrongly nullified attributes.

22 May 2014

Spectacle

for window management on mac

Oliver has another app to talk about, a free window management tool for mac. Its name is spectacle. http://spectacleapp.com

I know some of our devs have their own tool to control window between apple 27” display and mbp (like moon, but it costs 9.99~19.99.).

Spectacle is free and simple. It’s worthy to try this if you haven’t subscribed any window control application.

22 May 2014

Snip

for annotated screenshots

This week Stephen talks about a easy to use mac screenshot software snip. It will help you very easy to get shots like below, and you can also write text too when you capture. And it’s free.

https://itunes.apple.com/en/app/snip/id512505421?mt=12

snip

22 May 2014

jQuery serialize

not just for forms, also for fields

AaronK just met a little jQuery problem and googled the answer. We already know jQuery provide a easy method to serialize all the input elements became a parameter string, such as

$('#new_post_form').serialize()

But what if we want to just serialize partial input elements inside some div (or non-form element). Then we can just use

$('#div input').serialize()
22 May 2014

Hackpad cli

for storing pads locally

In Faria we use hackpad a lot, it’s pretty useful. Mose made a command line interface so he can download all the pads locally and grep them all in one go. It also transforms the markdown much better than the original hackpad markdown export, which totally sucks (as for now). So pads can be recycled easily in github wiki pages.

https://github.com/mose/hackpad-cli

22 May 2014

Email interceptor

to avoid spamming customers when coding

This is a tip from iHower : In KB/OA/iSIS, we have a trick to intercept outbound email at non-production environment, so we can make sure we will never send test email to real customers.

The key is a Rails API called ActionMailer::Base.register_interceptor and delivering_email method (since Rails 3.0.9). Basically it’s a hook that you can modify subject and address.

# in config/initializers/email.rb
DevelopmentMailInterceptor.init_if_needed!
# in app/services/development_mail_interceptor.rb
class DevelopmentMailInterceptor
  def self.init_if_needed!
    if self.should_initialize?
      ActionMailer::Base.register_interceptor(self)
    end
  end

  def self.should_initialize?
    Rails.env.staging? || Rails.env.development? || Rails.env.sandbox?
  end

  def self.should_intercept? (recipient)
    if ["@mydomain.com", "@internal.com"].find { |x| recipient.end_with?(x) }
      false
    else
      !(Admin.find_by_email(recipient).present?)
    end
  end

  def self.delivering_email(message)
    process = lambda { |getter, setter, placeholder = []|
      addresses = (message.send(getter) || [])
      message["X-Intended-#{ getter.to_s.titleize }"] = addresses.join(", ")
      message.send(setter, (placeholder + addresses.reject { |x| should_intercept?(x) }))
    }
    process.call(:to, :to=, ["devteam@mydomain.com"])
    process.call(:cc, :cc=)
    process.call(:bcc, :bcc=)
    message
  end
end