Defaultblog

Ruby on Rails QuickTip: Wrapping simple chunks of code in a method to give it meaning

ruby ruby on rails software

Let's say you have a model of a User. Let's say that if the user's birth year is 1990 or before, then you can't edit that user's first name. So you might have something like this:

# User Class class User < ApplicationRecord end

and you might have something like this

# User controller class UsersController < ApplicationController def edit if user.birth_year <= 1990 # don't allow editing of first name end end

However, I would argue, that even though it's a really simply check, that you should put this in its own method:

# User Class class User < ApplicationRecord def first_name_locked? birth_year <= 1990 end end

# User controller class UsersController < ApplicationController def edit if user.first_name_locked? # don't allow editing of first name end end

Very simple implementation and achieves the same result, but here are some advantages

  • The condition is now given meaning so that developers who are using it can understand its intent
  • Any developer reading any code that uses that method will understand more easily what's happening
  • If the business logic changes for locking the first name, you'll have to edit only one piece of code

So even the simplest pieces of code can benefit from wrapping them in a method.

Caseyli
Casey Li
CEO & Founder, BiteSite
Defaultblog

Ruby on Rails QuickTip: Adding Parameters to your Methods Safely

ruby ruby on rails software

This is going to be a quick post and applies to a lot of different languages, but it's something we've been doing in our Rails projects a decent amount.

If you're ever working on a larger codebase and you decide you want to add a parameter to a method, but are afraid to do so because it might break code elsewhere, consider simply adding a default value.

Take the following setup for example

class MyModel < ApplicationRecord def my_method(user_id) user = User.find user_id user end end

Now, let's say you want to modify this method so you can add another parameter. Here's a safe way you can do it:

class MyModel < ApplicationRecord def my_method(user_id, new_parameter=nil) user = User.find user_id if new_parameter do something end user end end

Now that new parameter's default value could have been anything, but the key here:

  1. Have a default value so that any code calling this method with the original parameters will still work
  2. When the new parameter is not passed in, have the method behave the exact same way it did before

With these two principles you'll be able to extend your code without breaking any existing code.

Caseyli
Casey Li
CEO & Founder, BiteSite
Ruby on rails accepts nested attributes for deleting records

Ruby on Rails accepts_nested_attributes_for is deleting my associated record!

ruby on rails software

So I've been programming Ruby on Rails for about 9 years now and I'm still learning new things everyday. This is one that definitely caused us some issues.

Setup

So here's the setup. We have a User model

class User < ApplicationRecord has_one :profile, dependent: :destroy accepts_nested_attributes_for :profile end

And we have an associated Profile model

class Profile < ApplicationRecord belongs_to :user end

Notice that on the User model, we have

accepts_nested_attributes_for :profile

If you don't know what that does, it basically allows you to run creates and updates on the User model and Profile model in one single call. So for example, you can do this:

user = User.first user.update({ email: 'test@example.com', profile_attributes: { first_name: 'Casey', last_name: 'Li' })

If you set up your form correctly and with proper strong params, you can put the User and Profile all in one single form for the user making it easy to update both models at the same time. BUT BE VERY CAREFUL!

Problem

If you have a very similar setup to what we had, basically a one-to-one relationship, then you have to be very careful of your update calls. If you call update on the parent record (in our case the User record), and pass in child attributes, if you DON'T pass in the ID, it will actually delete your existing child record and create a new one!. Yah. I didn't know that either. Try it out, and look at your Rails logs, you'll see a SQL delete statement followed by an insert.

Again, this is for one-to-one relationships only while doing accepts_nested_attributes_for updates.

Solution

If this is the behaviour you want, obviously you're ok. But for us, we wanted to update the existing child record rather than destroying what already existed.

If you want to update the existing record, there are two things you can do.

Solution 1: Pass in the ID of the child record

While I haven't tried this myself, if you pass in the child record's ID, it should perform an update rather than a delete/insert.

user = User.first profile = user.profile user.update({ email: 'test@example.com', profile_attributes: { id: profile.id, first_name: 'Casey', last_name: 'Li' })

Solution 2: Use the 'update_only' option

This is the solution we went with. When declaring your accepts_nested_attributes_for, you can pass in the update_only option:

class User < ApplicationRecord has_one :profile, dependent: :destroy accepts_nested_attributes_for :profile, update_only: true end

Learn something everyday. Hope this helps out some peeps. Thanks for reading!

Caseyli
Casey Li
CEO & Founder, BiteSite
Carrierwave 403 forbidden fix

Fixing Rails + Carrierwave + Amazon S3 403 Forbidden Error

coding amazon s3 carrierwave ruby on rails software

So we've been using CarrierWave for a long time now for our Ruby on Rails projects. Even when we converted to direct upload, we were still using CarrierWave for image processing. It has stood the test of time and I've heard from other developers that it offers more flexibility than ActiveStorage in its current state.

The Problem

We were implementing a very basic CarrierWave solution over the past while to upload files and attach them to an active record. The requirement was that the files that were uploaded needed to be publicly visible (so default CarrierWave behaviour). It's was very standard, basic CarrierWave:

  • Create an Amazon AWS Account
  • Create an IAM User that has full access to S3
  • Create a Rails initializer to use the IAM User Keys and Fog/AWS
  • Create a CarrierWave Uploader and attach it to the ActiveRecord model
  • Add the appropriate fields to the form
  • Get the user to upload files!

All good! This is what we've been doing for years and things have been working great.

But during this implementation, we got the following error:

Excon::Error::Forbidden (Expected(200) <=> Actual(403 Forbidden) excon.error.response :body => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>(obfuscated)</RequestId><HostId>(obfuscated)</HostId></Error>" :cookies => [ ] :headers => { "Connection" => "close" "Content-Type" => "application/xml" "Date" => "Thu, 14 Mar 2019 12:34:03 GMT" "Server" => "AmazonS3" "x-amz-id-2" => "(obfuscated)" "x-amz-request-id" => "(obfuscated)" } :host => "(obfuscated).s3.amazonaws.com" :local_address => "(obfuscated)" :local_port => 49582 :path => "(obfuscated)" :port => 443 :reason_phrase => "Forbidden" :remote_ip => "(obfuscated)" :status => 403 :status_line => "HTTP/1.1 403 Forbidden\r\n" ):

What was going on?

Realization of the issue

So it turns out the issue has to do with the fact that what we needed and what Carrierwave by default is set up to do does not play nicely with Amazon's current default S3 settings. We needed our app to upload files and make them publicly visible. However, when you create a new S3 bucket - it is not by default set up to allow that.

Solution

So how to you fix it? You want to go to your bucket and click on the "Permissions" tab. From there you want to make sure that both "Block new public ACLs and uploading public objects" and "Remove public access granted through public ACLs" are set to false. There is a little "edit" link in the upper right to allow you to set this. You can even read the little blurb about these settings if you hover on the "i" icon when you go to edit and you'll see that these control, you'll see that these affect objects uploaded with public ACL settings.

So set those to false and that should resolve the issue.

Be careful

Now one thing I should mention is that you might want to be careful when it comes to your app and your specific security requirements. Our app was all about posting public files. If you're in a situation where you need more fine grained privacy control or are dealing with sensitive files, you might want to look into creating custom policies and custom users. The solution I've detailed here is a barebones, public file upload solution. It's also a good way to just get things going if you're in a prototyping phase or in that phase where you just needs to get things working.

Hopefully this helped some of you out.

Thanks for reading.

Caseyli
Casey Li
CEO & Founder, BiteSite
Howmuchdoescustomsoftwarecost

How much does custom software cost?

buiness software

If you’ve been reading our blog lately, chances are you’re interested in custom software. Recently we’ve written articles about what custom software is, the pros and cons of custom software, and how to get started with an MVP.

This may have peaked your interest a bit and it may have you considering your own project and which direction to go. In the early planning phases you might start to weigh out your options between the status quo, using a pre-existing application, or building some custom software.

There is a lot to consider when making your decision, but inevitably, one of the biggest criteria that will factor into your decision is cost.

Now, we briefly talked about cost in our Pros and Cons of Custom Software article and how custom software can be expensive. The question is, though, how expensive?

Invariably, when writing articles about cost you have to be careful. There are so many variables that factor into a given company and how much they charge and there are no blanket statements that apply to all companies. It’s probably a reason why most companies don’t talk about the subject publicly.

The reality is, for the same software output, you may pay someone $200.00 and you may pay someone else $20,000.00. The discrepancy can be that big. But you have to consider that for the same software output, you might not exactly be getting the same service. Sure you may end up with the same basic application, but what’s different? Does the person you’re paying have years of experience behind them? Do they have a team that will help you in case things go horribly wrong? Do they have processes that make the development cycles more efficient and less stressful?

These questions just scratch the surface of what can differ from vendor to vendor. But besides your project, you have to consider what the vendor has to account for. If the vendor is an individual working out of their home, they will obviously have way less to pay for than a team of 20 working out of an office. Any business owner will tell you how high costs can get.

Another factor is simply the types of clients that the vendor deals with. Some vendors deal with huge organizations that spend hundreds of thousands if not millions of dollars on custom software projects. These vendors will naturally price themselves for those customers. In some cases, it’s due to the fact that these types of customers have way higher demands, but in other cases, it’s simply what the client is used to paying.

So when thinking about the cost of custom software, you have to do a bit of thinking about anything you hear or read and understand that there is a LOT that goes into the number that someone gives you.

I can’t speak for other vendors and how they do things, but I can write about how we runs things at BiteSite. I would assume that most vendors follow something similar, but again, I’m only speaking from our experience.

The problem with Fixed-Price Contracts

When BiteSite started, our contracts and projects fit into two categories: fixed-price and hourly billing. For the Fixed Price contracts, here’s what our pricing process would look like. We would sit down with the client, discuss the project, sometimes breakdown the project into milestones, and agree upon a feature set. We would then take that feature set and estimate how many hours it would take, multiply those hours by our standard rate, and draw up an contract based on that number.

Because we had seen other companies do this, we thought this was the way to go. But after a few projects that went way over budget and after reading Thoughtbot’s Open Source Playbook - we had the confidence to say “This is not working out.”. (in fact, Thoughtbot taught me the phrase “Fixed-Price Bid”).

The problem with software development is that it’s usually best developed in an agile manner. That is, with shifting priorities, MVP philosophies, and incremental changes based on continuous feedback. When you put all those principles in place, software development is generally very hard to predict and map out exactly over a long period of time.

So if you come up with a contract for a 2-3 month project, there is an incredibly high probability that things are going to come up that you didn’t envision. In fact, if you’re a good agile developer, you welcome the unforseen feedback that causes you to shift course.

With that in mind, we abandoned fixed price contracts for all of our custom software projects and moved purely to a hourly based billing system.

Making our clients feel comfortable

So going to a hourly based billing system was great for us. Not only were we not going over budget, but we didn’t stress anymore about beating the clock. We did our work at a comfortable pace which in a lot ways allowed us to do better work.

So that’s all well and good for us, but what about the client? When a client approaches you about creating something for them, it’s hard for them to hear “We’re just going to build it, and charge you at the end of the month.”

With fixed-price contracts, they knew exactly how much they were going to spend. With hourly based billing, they were left in the dark and just had to trust us.

So to combat this, we married our hourly-based billing with a couple of other concepts:

  • Rough Estimate: While we don’t do fixed price contracts, and we don’t stick to a specific number, based on what the customer is asking, we do give a rough estimate. For example, we’ll tell them that what they are initially asking for will take roughly 30 hours and multiply that by our hourly rate.
  • Re-emphasize that the rough estimate is purely an estimate: Despite giving them an estimate, we still emphasize that software is unpredictable and that a lot of unforeseen development may come up.
  • Transparency along the way: If money is a big concern, we let our clients know along the way how many hours we’re spending. We informally agree that if we’re coming close to the rough estimate, we can sit down and chat to make some decisions.

With these three things in place, it helps the client agree to work with us.

The last thing though, is that there has to be a trust between us and the client. In our first meetings, based on our interactions, based on our previous work, based on our reputation, there grows a trust that we will do our best work and not overcharge you. Once that trust is established - both parties stop watching the clock and dollars and start focusing on the project.

This trust between client and vendor is something that should exist with any company you choose. Thoughtbot has a great article on this here.

So, how do we price?

With all that in mind, our pricing becomes pretty easy. For starter projects, we figure out a rough scope of features, we do a rough estimate of hours, and give the rough number to the client understanding that it can fluctuate.

After the project has some legs, usually it moves to on-going work. Our clients ask us for work to be done, we do the work, and bill at the end of the month for our time. If the client is concerned about cost at that point, we do an informal estimate of hours as well.

Stop skirting - what are the actual numbers?

Like I said, vendors vary heavily in cost, and even in our lifetime, BiteSite has changed its rates several times and will probably change them again in the future. WIth that said, as of the time of this writing, our standard rate for software development is $150.00 CAD + HST per hour. That is a standard hourly rate that covers all of our services. We’re a small team so our staff are jack-of-all-trades that cover everything from Product Management, to Design, to Coding, to Deployment - basically everything you need to get a software project off the ground.

When we start a project with a client, we usually like to scale down their big vision to an Minimum Viable Product or MVP. Because software can be very unpredictable to develop, it’s good to come up with a small product that can generate valuable feedback that we can build upon.

Our best MVPs have been in the neighbourhood of 30-50 hours of work. So a good starter project would cost anywhere between $4500.00 CAD and $7500.00 CAD + HST.

So as a rough start, we usually tell our clients that $5000.00 + HST is a good starting budget.

So what can a $5000.00 MVP get me?

So what does 30-50 hours of work look like? At BiteSite, we focus on Web Applications so let’s talk about those. Client features have a big range, but here's an example project to give you an idea:

  • A web application
    • that allows my staff to login and manage their account and profile
    • that automatically calculates total vacation days an employee is entitled to based on their start date
    • that allows my staff to request their vacation days
    • that allows supervisors to approve vacation days
    • that allows supervisors to customize how many vacation days each employee is entitled to
    • that e-mails supervisors anytime someone has logged a vacation day
    • that e-mails staff anytime their vacation is approved
    • that summarizes total vacation days in a report

This is a very high-level description, but it’s a good example of a good MVP. If a client came to me with that description for a project, I would say that’s a great starter project that would probably cost around $4000.00 to $5000.00 + HST.

On the subject of the MVP, we try as much as possible to get our clients projects down to something in the range of 30 - 50 hours because we feel it’s a good spot when it comes to foreseeable development. Anything past that, we feel it’s better to develop something small now and see what happens later rather than plan out every single detail.

What happens after the MVP?

After an MVP is launched, it’s really anyone’s guess how much more you will spend. Depending on many factors including how much you're dedicated to the project, how much the software gets used, and how "on the mark" the original features were, your software could demand a lot more future work or very little.

If the software is very successful and you want to keep adding more and more to it, it’ll cost you more. Chances are though, it will also help you more and potentially generate revenue for you. On the other end of the spectrum, you may find that the MVP is perfectly fine and just needs a few tweaks every now and then.

We’ve had projects that have become very successful and demand full time work where over hundreds of thousands of dollars of development are spent every year, and we’ve had small projects that cost under $100.00/year of maintenance. After your MVP though, you start to get an idea of how much effort it takes to add to your product and if you don't - that should always be an open conversation with your vendor.

So when considering custom software, it’s a good idea to think about your initial MVP cost, and then the potential to fund it afterwards. While our clients may have way bigger budgets, we still encourage them to start with the MVP and go from there.

The fine print

This article is called ‘What does custom software cost?’, and while the majority of your cost will be spent on labour, I would be remiss to leave out the extra costs that a client is typically responsible for. When it comes to developing software, there are usually a lot of services involved that you’ll pay for. For example, if you want to develop an iOS app for the iPhone, you’ll have to pay $99/year to have it on the App Store. If you want to develop a web application, you’ll have to pay for the domain and hosting costs. So when considering your budget, don’t forget to discuss with your vendor any extra costs on top of the service labour they’re providing.

Conclusion

Like I said, I can only speak to our own company which is basically a $150.00/hr rate. Other companies will have lower rates and others will have higher. Some will do fixed price - but the fixed price probably factors in some hourly estimate of the project.

So if the price can vary so much - what’s the point of this article? First of all, I wanted to educate the market on where the price is coming from. Second of all, we at BiteSite want to be transparent about our pricing. It helps with our own projects and helps push others to be transparent.

Not to mention, I hate when I look around the web and can’t get a single answer to a question I have. If your question is “How much does custom software cost?”, well now you have a starting point.

Caseyli
Casey Li
CEO & Founder, BiteSite