mines!
a developer developer's development log
20141125
A modern day blog engine?
20141013
Bash Contexts Cont. (for those still bashing)
./.bashrc
's and the following line at the end of ~/.bashrc
So, to make this technique complete (and to support login shells starting from non-home directories, like with Terminal.app's Resume), you must also add the following line at the beginning of ~/.profile
20140605
pow and byebug - staying in the web app dev env heaven: an update for ruby 2.1
It seems ruby-debug has fallen out of favour with the community and the replacement is byebug.
So here's my follow-up on the old post.
The steps to enable byebugging in your app dev env:
- echo export POW_WORKERS=1 >> ~/.powconfig # make sure pow runs only one app process — globally
- cd <your project directory>
- Add byebug to your bundle (and remove ruby-debug if exists).
- Paste the following snippet at the end of your config/environments/development.rb — for rails, or in the appropriate development environment initialisation module — for the platform of your choice:
- echo export RUBY_DEBUG_PORT=10007 >> .powenv # make sure we enable debugging with a machine-unique port, e.g. 10007 (you should pick different ports for different projects)
- touch tmp/restart.txtThen make any request to actually restart your server.
- byebug -R localhost:10007 -d # you're back in business, go wild with debugger's in your code
20140422
A Nice Support Chat -or- Skype R.I.P., Goodbye M$kype
20140330
mail_view for human — and also for automatic — testing
I've come to use a nice gem called mail_view for visual testing of email templates in Rails.
I think it is totally legit and desirable to re-use that code in the views testing suite, so here we go:
(provided that your MailView
's subclass is MailPreview
, put this in ./spec/views/mail_spec.rb
)
This just checks for the lack of exceptions and any content, but it's a starting point.
p.s. A nice complementary pull request of mine is here.
20140122
The ruby hint of the day: Hash#fetch
hash.fetch(key)
instead of hash[key]
whenever your Hash
is constant and you expect the key to be one of the hash keys — it will raise an exception if not found. Early bug detection you see.20140116
I18n testing outfit for Rails 3.2 (also Rails 4.0-stable)
Now put this in config/initializers/i18n_test.rb
and spec it!
N.B. Curiously enough, a similar technique is needed for 4.0 as well.
P.S. Tested and working with Rails 4.0-stable, yay!
20130529
HTTPS in local development environment (with subdomains, stunnel and [optionally] pow and [bonus] iPad)
First, I've found no reason not to use pow, both for same-machine (via http://somesub.yourbaby.dev) and same-network (via http://somesub.yourbaby.192.168.1.111.xip.io) testing.
Tip: even if you don't fancy pow, and use different ports for running stuff instead, you can still use this technique with http://somesub.lvh.me:3000 (same-machine, resolves to 127.0.0.1:3000) or http://somesub.192.168.1.111.xip.io:3000 (same-network, resolves to 192.168.1.111:3000), somesub being any subdomain.
Then, we're going to use stunnel to put that SSL on top of our fine-running web app. So, I've compiled a little script to automate the stunnel certificate + configuration generation, here it is (any patches/comments are welcome). Install/copy it somewhere, then go to your project's directory and run:
stunnelo.sh yourbaby.192.168.1.111.xip.io
Hopefully, it will produce all the necessary files in
./var/stunnel/yourbaby.192.168.1.111.xip.io/
Finally, you may run (in a dedicated terminal window):
stunnel var/stunnel/yourbaby.192.168.1.111.xip.io/stunnel.cnf
then hopefully go to https://anysub.yourbaby.192.168.1.111.xip.io and see your same old app running in total security.
Wait! In a moment you'll notice your browser not being happy about the certificate we've just created, so here's a...
Bonus:
The self-signed certificates this technique creates are obviously will not be trusted by any browser on any device by default. This will get even more messy if your app involves a number of services you're running in the same dev env.
For computers, a browser will usually allow you to install the certificate in question when it sees it, so you will be annoyed just once. For iPads/iPhones — that's what same-network testing is for — you will have to take var/stunnel/yourbaby.192.168.1.111.xip.io/stunnel.crt and mail it to yourself, then open the attachment on your iPad and that's how you install the certificate there and go debugging.
Obviously, you can have any number of such stunnel configs in
./var/stunnel/
— go wild with the domains you are to test.p.s. I've tried to use tunnels, but it provides no means of control over the certificates and thus, complicated scenarios bring... uh... complications.
p.p.s. Thanks go to xip.io-cert for outlining self-signed certificate generation.
20130121
rails 3.2+ controller specs helper for extracting a model object's accessible attributes
20121119
subdomains in rails apps: a current brief
Subdomains (or second level domains) are still a nice way to present separate interfaces to a single web app — commonly to give a certain kind of customers the feel-n-touch of a dedicated app install.
Here are most of the related aspects based on a particular Rails3 project:
some model
Group
, representing a customer, or rather a group of users, has a string columndomain
(migration not shown, but don’t forget to index by that column)in
app/models/group.rb
:has_many :users before_validation :downcase_domain, :if => :domain_changed? validates :domain, presence: true, uniqueness: true, length: {maximum: 255}, format: /^[0-9a-z-]+$/ def host "#{domain}.#{ROOT_DOMAIN}" end protected def downcase_domain self.domain = domain.to_s.downcase end
under assumption that you’re using
devise
and your (group’s) user identity model isUser
(updated for everchangingdevise
2.0.4)in
app/models/user.rb
:belongs_to :group devise :database_authenticatable, ..., :request_keys => [:app_subdomain] def self.find_for_authentication(conditions={}) group = Group.find_by_domain(conditions.delete(:app_subdomain)) return nil unless group.present? conditions[:group_id] = group.id super end
you’ll have some admin interface where the
groups
are managed (e.g.active_admin
, not recommended)in
app/admin/groups.rb
:link_to group.domain, root_url(host: group.host)
you will certainly want to do something specific in
config/routes.rb
you’ll want some handy helper method, to know which guvnor you’re serving
in
app/controllers/application_controller.rb
:helper_method :current_group def current_group return @current_group if defined? @current_group @current_group = request.app_subdomain && Group.find_by_domain(request.app_subdomain) end
you’ll need an initializer of some sort to set a constant and monkey-patch the request class, so…
in
config/initializers/subdomain.rb
:ROOT_DOMAIN ||= ENV['ROOT_DOMAIN'] or raise "ROOT_DOMAIN must be set" # (): paranoid monkey patching :() class ActionDispatch::Request def app_subdomain return @app_subdomain if defined? @app_subdomain @@app_hostname_regex ||= /^(?:([0-9a-z-]+).)?#{Regexp.escape(ROOT_DOMAIN)}$/ raise 'Wrong domain' unless host.downcase =~ @@app_hostname_regex @app_subdomain = $1 end end
then, for your production (and staging) environment on, say, heroku, you’ll have to setup your lovely app domain name (with wildcard subdomains) and set the environment variable
ROOT_DOMAIN
to itfor test environment, which is also good for the handy circleci
in
config/environments/test.rb
:ROOT_DOMAIN = 'lvh.me' # yes, it's a magic domain for 127.0.0.1 //smackaho.st RIP
for other environment cases, be sure to set either
ROOT_DOMAIN
orENV['ROOT_DOMAIN']
as appropriateif you use factories (and girls,
factory_girl
)in
spec/factories.rb
:factory :group do sequence(:domain) {|n| "dom-#{n}"} # or better still, use `forgery` with some smart randomness ... end
if you use
capybara
(2.0.0 at least, recommended) andrspec
(rspec-rails
2.12.0 at least)in
spec/spec_helper.rb
: (inSpork.prefork
block if you usespork
, recommended)Capybara.always_include_port = true # unless you `visit` external sites in your feature specs
and then in some
spec/features/..._spec.rb
:visit("http://some_domain.#{ROOT_DOMAIN}/some_path") # or visit(some_url host: @group.host) # if you're playing dirty, using pre-fabricated data and route helpers, recommended
in some
spec/controllers/..._spec.rb
you’ll have to include something like this:before(:each) do request.host = @group.host end
don’t forget the specs for domains in
spec/models/group_spec.rb
and other relevant places
May your sub-domains be obedient to their master.
20120608
app cache manifest should be public
20120513
clothing labels hell
They are mostly made of highly skin-irritating fabric, and they tend to outlive any piece of clothing they are super-securely attached to.
Why???
20120510
Buggers Must Die
But.
I think they've just crossed the line with the “New Gmail Look”.
BTW, I hope you understand the irony of the first line: I really don't think I must feel obliged for their “free” email service — however good and accessible it is; quite the contrary, I feel I'm contributing to Google an irreplaceable and precious source of real-time information — the stuff the most world's (and certainly Google's) money comes from.Personal opinions and tastes aside, the New Gmail Look is effectively incompatible with Mozilla Firefox — I know nothing of its compatibility with the new “good” Internet Explorer, unfortunately — and is clearly (cleverly) targeted for Google Chrome. To be clear, Gmail is functional in FF, but its CPU consumption there makes the combination unusable.
This is not something new or unexpected, both FF and Gmail have undergone development with this problem known — there are discussions, bug reports and blog posts like this one all over the internets — and I've been hoping a solution will be found before the New Look would become the only look, but alas, ah-ah, nope. At this moment, I have my peaceful internet existence violated and I feel forced to use the Chrome: Safari is also okay wrt Gmail, but it hasn't got nearly as much plugins as Chrome or especially Firefox have, so not much choice for a single-browser setup.
I don't think it's a fact to be taken lightly. I see something much worse than Microsoft coming, and I personally will now always try not to use Google products as the first option. Luckily, most alternatives to Google products actually outperform the latter.
Erm, yes, this blog will also be moved to a different provider in the nearest future.
p.s. Unrelated, kudos to Apple for making the choice of English flavour finally available system-wide. Alleluia!