All Posts in Development

September 22, 2014 - No Comments!

Enhancing your Ruby experience

Writing more readable ruby code

Best thing about ruby, is that it’s clean. You feel more writing english than writing code. Sadly I didn't realize this before, and if you are new to ruby and rails. You're probably writing code like this …

It might look normal to you because you're used to it by now, but it has adds overhead when reading. You have to read every line translate it, keep variables flow in mind, and remember what each function does. And if you have like 20 lines, that would be even more pain in the ass.

Instead why not write instructions directly. Why not say what you want to say in plain english.

This doesn't eliminate the coding part. It just gets it deferred to private methods. When reading public methods, you don’t care about the flow of variables or which method gets called, you only care about the big picture.

This helps by making public methods scannable, something that you can read. Something you don't have to compile in your mind.

It makes your code DRY, and constructed of small single tasked reusable methods.

To wrap up

  1. Move all class calls and assignments into small private methods, each responsible for one small task.
  2. Write more descriptive method names, it’s ok to have long names, but not very long. Take your time thinking about it, and make sure that it’s clear what the method does. e.x. authenticate_using_email, sorty_by_popularity, filter_by_author, …etc.
  3. Prefer use of instance variables (@variable) for global assignments over passing parameters, and assigning them back to another variable.
  4. Optional: Use rubocop to help you follow Ruby style guidelines.

Do you have a better way or tips on enhancing this? would love to hear your thoughts

If you find this helpful, don't forget to hit Recommend button

January 13, 2014 - No Comments!

4 Things I wish I knew when I started Rails

Or MVC in general

Ruby is awesome, and Rails makes it even more awesome. I started my journey with Ruby on Rails about a year ago in order to make an API for asknative app for iOS. Before that I only did very little PHP and mostly frontend stuff. Anyway, here is what I wish someone told me when I was getting started.

1. Cache from the start

Caching is critical. If you didn't cache from the start you are never going to cache. Caching is a pain in the ass, and as long as you delay its going to be harder to add. Thinking that there is no need for adding cache, when you are getting started because there is no complex queries yet. Is the first step toward a bigger problem later.

In our case, we tried to add caching later in the process, and failed to do so. We've spent around 3 weeks trying different solutions with no luck. We ended up delaying this issue again, because the serialization gem we were using was not very handy with external cache, and requires to use its caching layer. Their caching system didn't work well with us, and they were rewriting their gem again to improve it and rethinking about cache. So now we either remove this gem or just wait till they add caching.

I'm not blaming them for that, it’s our problem that we didn't find out about this from the start. So do yourself a favor and setup caching from the beginning.

2. Never slack on Testing

Startups is about sprinting. Features will be added, modified, and removed and it has to be done fast. We tend to think the testing is an overhead. Maybe because your tests take too long to run. Maybe because you see the time take for adding necessary tests will be a waste of time. Maybe because specs are going to change anyway. Or maybe you are so confident of your code that you don't need to test your code.

The moment you say we'll do tests later, you are surrendering to your code. Testing is never a waste of time. And it is very important specially when you are in a startup. Because there is alway a constant change it means that you need to have a way to be 100% confident when you apply those changes to production.

“Move fast and break things”

Of course, but that doesn't mean you should do it intentionally.

Testing is tedious, takes time and effort to do it right, not fun, and sometimes it takes longer time to fix testing bugs. But having tests will make you the owner of your code, not a slave to it. Scared of touching your code or others code not to break anything. Scared of pushing to production, because you have to test it over and over to make sure nothing breaks.

3. Lazy requests

In any request, avoid doing any work as much as possible. If there is a task that is not directly related to the request, it should be running in the background as a worker.

Lets say there is a request that should update user profile. You only need to validate the data, then return ok to the frontend. Unless you are working with sensitive information, there is no need for the extra delay added for inserting or updating record in the database. Even if the request only sends one request to the database there will be callbacks and triggers firing all over the place before, after storing.

Maybe you're afraid that something would go wrong after accepting the request and you have to be absolutely sure. But how often does that happen? Lets say 90% of the request will get accepted, so why not make it faster for those people. Why do we have to make them suffer because of that?!

4. Put your code on diet

Thin controller, Fat model

“Thin Controller, Fat Model” OR “Just move all your logic to models. It’s that simple.”

These are the worst advice ever. I don't know why a lot of people in the rails community are recommending this, but it has to die. Models are not your magic bag.

At first I was using models for everything. Everything that does something that used to be in the model. But browsing the model was nightmare. Attributes, queries, callbacks, validation, methods. One class rule them all.

Moving to Concerns seemed like a good option. After all its added by default in Rails 4. Moving all the common code in there, even it was used as a component for new features. Models looked much better, but then we realized that concerns is hiding under the rug. At some point scopes were a mess. And adding logic that talks to different models there makes the matter worse. Concerns are useful in very little cases, like having same attributes share between models, maybe queries too (but it’s arguable)

Micro API

MVC is great, but its not enough. Don't limit your choices to either make fat controller or fat model, it will make your code harder to maintain. If you have bunch of code that needs to do something specific with many models, why not just create an object for doing that. Has its own api, and does a simple task, and thats it.

Working with single responsibility objects makes it easier to test, easier to read, easier to modify, easier to replace.

People used to put logic in controller for a reason. It can tell a story. If you read a controller you should have an overview of what it does. And its a good practice for the upper layer to control the ones below, and avoid same level objects to communicate to each other.

Having a middle layer between Controllers and Models minimize if not eliminate any logic in the controller, controllers will be more like a story. And changing models will not affect controllers because it doesn’t know about models. Service objects become like a genie, controller asks, and service objects will make that happen.

This applies to the Views too. You can add View Models or Presenters to pass the data into your views. Without making your views know anything about the models, relations, or how to format the data. Views will be so dumb that you don't have to test.

The less each layer in MVC knows about each other the better. If you changed your database from MySQL to MongoDB it won't matter. Each layer will be independent, and applying changes will be much easier.

To recap

  1. Think about caching from the start and get it to work.
  2. Never submit code without it’s tests.
  3. Never work with database in a request unless its absolutely necessary. Other than that, throw it in worker in the background.
  4. Use PORO (plain old ruby objects) to create layers that separate each part in MVC.

If you find this useful, please share it ☺

March 30, 2013 - No Comments!

The Rails Code

Here is a few stuff that, I wish I knew, or I forgot along the way when developing asknative’s API. Just know that I didn’t have any previous REST or Rails background before that, so keep that in mind while reading.

Code Structure

  1. Controllers. Its job is to take data from the request pass it to models, then pass leave it to views. So don’t put any thing more than that, not queries not JSON response messages.
  2. Models. Defines your documents(tables in SQL), relations, queries it, and other functions thats needed for the model or controllers. It’s like helpers for Controllers. Most of your coding will be here.
  3. Views. Can be HTML, or JSON. So never define put conditions there nor queries. Thats what are helpers for. Even if you just do simple user.count.
  4. Helpers. Used for handling simple and complex functions that is only needed for the views. If you need something outside views scope, define it in the model. Else go with helpers. This will make your code readable, more easy to change, and accessed by other views.
  5. Gems. Give you extra predefined functionalities without messing your code.

Controllers = Managers (They never do actual work)

First thing to know is to keep your controllers thin, and models fat. Controllers are supposed to connect, and thats it. It manages everyone, so don’t put extra work on it. Because if you did, it would really be hard read or change your code unless you do that.

Use before_filter in controllers to handle repetitive tasks like User.find(params[:id]), and make sure you define who will need this using only and except.

If you have something that takes parameters, and needed in all controllers like limit and skip, you can define it as a protected function in the ApplicationController so that it can be accessed and changed for all the application.

If there is a case that you still don’t want to create a function in the model that handles specific tasks in the model, then create a private function that will be called in your controllers. So that you still have a clean and readable code.

As a general rule, controllers should only call functions, and if conditions that call specific functions for each situation then pass it to views. I can’t stress this enough, but this is the most important place to be readable, when you look at it, you should know what goes where and to whom.

Models are Fat

Models are helpers of the controllers, if you need a query or a function, it should be there. You can use def self.query to use it like this User.query without having to define it first. Which comes in handy for listing queries. But incase you need something simple go with scopes, they are simple and more efficient.

Use model callbacks like after_save, and before_save to handle errands. If you want to notify the user when there is a new post, then put it in after_save method.

Gems are cool

Everyone talks about how bad gems are when you are getting started with Rails, I disagree. I think they are amazing, as they help you see how you can do things correctly. Because when getting started no matter what you do you will mess things up, so I believe don’t try to run before you can walk, don’t get ahead of yourself. Use gems, and when you become strong enough, you can create your own gems that are specifically tailored for you.

Respect for RSPEC

I’m guilty of being scared of testing. I thought it was hard, but it turned out to be a life saver. It is extremely easy, and will get out of your way. You don’t need to open the browser to test a case, and you can’t the whole application in the browser every time you want to deploy.

Whats awesome about testing is that you can test everything, without doing it yourself. You don’t have to remember all the cases which broke your code. You just have to write it down.

For me I started doing this lately, so I still write dump repetitive code, but it works great.

Use watchr while you are refactoring so that it makes sure that nothing breaks, and if it does, you can handle it quickly.

Before deploy just run your test, and save your self some embarrassment after you deploy and find a stupid issue.

If you like this post, stay tuned for mongoid tips post.

March 21, 2013 - No Comments!

Passwordless SSH to Ubuntu

I know this is a no brainer for most people, but it took me sometime to do it, so incase anyone having problems with connecting via SSH to Ubuntu here is a simple walkthrough.

  1. Create or Copy Development machine’s public RSA located ~/.ssh/id_rsa.pub
  2. Login to server and paste it in vim ~/.ssh/authorized_keys
  3. Ensure that /etc/ssh/sshd_config contains PubkeyAuthentication yes and RSAAuthentication yes uncommented
  4. Finally set chmod go-w ~/, chmod 700 ~/.ssh, and chmod 600 ~/.ssh/authorized_keys to make sure that permissions are set correctly

Update

For more information check this guide
http://library.linode.com/securing-your-server . Thanks to @kamasheto

February 18, 2013 - No Comments!

The Hybrid Era: Marriage of the Web and the Native

Why don’t we all just go web?

This idea doesn’t sound very good and there are lots of concerns, but it is worth it when done right.

The beauty of it lies in being easy and fast to push updates. Thats one hell of a problem when developing on iOS. Making a big deal for each and every update.

Another thing is not worrying about porting too much. You just port views and animations, but the content will be there.

There are lots of libraries out there. Problem is it doesn’t have the seamless native feeling yet. But we’ll get there very soon.

I don’t think native developers will die, but i don’t think the need for them will be as it used to be. Things are getting interesting much more interesting. The line is getting blurry and we are on our way to a one platform rules them all.

So whoever wants to rule the next 1-2 years you should be great at doing native web-apps on your mobile platform.