There was some discussion last summer about changing the generally accepted best practice implementation of box-sizing in CSS. Something about it didn’t quite sit well with me when I saw it, but I didn’t really suss out what it was until I started on a book project (more on that later).
The previously accepted practice was proposed in a blog post by Paul Irish (the post has been updated so I’ve duplicated the code in a slightly modernized format (no browser prefixes) below).
The latest accepted practice is:
The main benefit of the latest practice is that you can have an entire widget (or component) that uses a different box-sizing model easily. This makes sense if you have to do it a lot, but in my experience this change to standard behavior is not needed very often. The box-sizing will only apply to block-ish elements and it’s not terribly difficult to override the box-sizing in your CSS exactly where you need it (you can even create a @mixin or @extend-only selector). However, if a developer on the project sets box-sizing higher up in your DOM without anyone realizing it, then the style would cascade throughout many elements via the inherit and is likely to break the layout – possibly in difficult to debug ways.
There are certain styles that you expect to be automatically inherited (mostly font-related). You don’t expect something like box-sizing to be inherited and that’s where the surprise comes in. We should always be working to minimize surprises in our work and I don’t think that inheriting box-sizing does that. Sometimes a little surprise is acceptable for a bigger gain, but inherited box-sizing doesn’t provide enough gain.
Form placeholders have a very specific syntax to style and it varies from browser to browser. This is compounded by the fact that you must specify each selector in its own group because browsers will invalidate a selector group if it doesn’t understand one of the selectors.
Taken together, in order to specify styles for placeholders, you need to duplicate your styling in 4 different blocks. You can get around this by using a mixin for the styles (you can’t use an @extend because that would merge the placeholder selectors into a single group) but you’re still having to repeat the placeholder selectors.
This mixin makes it easy to have a single line in your Sass for placeholder styling which is then output as multiple selector groups.
Some clues to this are that you are seeing the *.herokuapp.com cert being served when you try to access your subdomain via SSL.
Also, I had to remove the subdomain before Heroku would add the SSL cert since I was trying to use the subcustom domain for SSL. If you are putting the SSL on a different subdomain then this is unlikely to affect you. I did initial work without SSL then wanted to add SSL before release.
Recently I was working on a Rails app where every user who signed up also needed to be assigned to an account. Since User and Account are two different models, this can be a bit ugly to handle when Devise expects a single resource. However, by leveraging Reform we can use the Form Object Pattern (#3) to create a RegistrationForm that composes Account and User for registration but doesn’t require creating unnecessary linkages between the actual models.
In this post, I’ll walk through the code on how I made it work. I won’t delve too deeply on actually getting Devise setup since the Devise documentation does a pretty good job of covering that. Just note that you will need to copy the Devise views into your app and you will need a local RegistrationsController that inherits from Devise::RegistrationsController.
Let’s start first with the tests. This will show you what we want the final experience to look like.
This is a basic controller test that lets us validate that we can send a post request with the form parameters and the expected objects get created. Please note, even though we will be using a RegistrationForm object, Devise thinks that we will be using a User object and so we need to use :user params to keep Devise happy.
Please note, I am using factory_girl_rails to get the attributes_for methods. Also note the necessity to specify the devise.mapping; this is discussed further down in Some Final Caveats.
This is a basic feature test to verify that the process works as expected for a regular site user. The page after a successful login contains the word “Welcome”.
The Form Object
As stated above, we are using Reform to implement a Form Object so that we don’t need to insert any logic into the User or Account models to support capturing fields for both models on user signup.
First take a look at the code for the entire form, then we’ll walk through it step-by-step.
Standard Reform Stuff
The first half of the code is standard Reform stuff. We are using Compositions for cleaner fields, setting up our properties, and configuring validation.
Satisfying Devise Processes
The #active_for_authentication? and #authenticatable_salt methods are to make Devise happy because it’s trying to treat the RegistrationForm as if it was the User model with all of the Devise authenticatable methods mixed in.
Saving the Record
The save method is the most interesting thing here (combined with #build_resource from the RegistrationsController below). The Devise::RegistrationsController#create method expects to work with a standard ActiveModel object where the model is validated at the same time that it is saved. However, Reform uses the validation process to actually populate data into the object and validate it. Saving (or syncing) is a separate step. Here is a snippet of the Devise #create method to see what Devise is doing
As you can see, Devise expects the output from resource.save to indicate if the record is valid. Since we need to check validity differently with Reform, we have our own #save method in the form which fails fast if the RegistrationForm is not valid, but actually handles the save if it is.
This is a fairly straightforward implantation of a custom Devise controller with one twist.
As noted above, Reform uses the validation process to populate the form with data from the params hash. Since the #build_resource method is the only time we can get access to the params hash from Devise, we need to validate there so that we have the params data for later usage. But, #build_resource gets called from both #create and #new; and when it’s called from #new the hash is empty. If we try to validate with an empty hash we’ll show the signup form form with validation errors – definitely not something that is conducive to people signing up.
The view is pretty standard. Only significant thing to note is that we are treating the :company_name field as if it belongs to the resource – which in this case it does. It’s not a field on User, but it is a field on RegistrationForm which is the resource for Devise.
Some Final Caveats
Reform and SimpleForm
The latest version of Reform has some issues with SimpleForm. I’ve been working with the Reform maintainer on a patch but you may need to use my fork of Reform.
RSpec and Devise
In order to get RSpec to work correctly with Devise in controller tests, you will need to edit your spec file and your rails_helper.rb (or spec_helper.rb if you’re running an older RSpec). The Devise How To: Test controllers with Rails 3 and 4 (and RSpec) wiki page has the details.
I’m working on a Rails project and wanted to validate that the Devise User Registration path was working as I expected. A quick google search turned up Devise Integration Tests With rspec which was a good starting point, but there were a few things I wanted to change.
Break the test up to have only one assertion per block
Update to use RSpec 3 and the expect syntax
Use capybara-email methods for clicking email links
You get better at something by practicing. You gain a better understanding by teaching and sharing. I’ll be combining these ideas by blogging my activities practicing the craft of web development. I plan to build a simple project every few months to explore new areas and technologies and grow my knowledge and experience.
My first project will be a utility tracker. I want to be more aware of our utility usage and tracking it will be a good way to increase my awareness.
My plan is to create a single page app that leverages offline storage and syncs with a Rails back end. I’ve thought about adding push notification as a reminder to take measurements and I’m sure that charting would be good to have but the first thing is just to get a simple app out and usable.
Capabilities of my MVP will be:
Select a utility
Enter a value
Save the value
View a list of saved values
Initially it will not be backed by a persistent storage. This let’s me avoid server-side services and any kind of user login. I may add support to export and import data to enable some kind of rudimentary self storage, but my initial goal is to keep it simple.
A followup blog post will discuss the technologies I’m considering and talk through why I’m planning on using what I’m planning on using. I may pick something that’s not as appropriate as something else. I may encounter issues and change my approach. We will have to see as we go. In any case I will keep the repository public and discuss approaches, issues, and resolutions here.
With the app, you’ll be able to create an account to track your own weight-loss or get-fit statistics and join teams to work towards your health goals with other people. The app works on your desktop, tablet or phone so that it’s easy to capture exercise details when they happen.
This was launched on a very short timeline so the features are a bit limited but we’ll be adding more throughout the 8 week challenge.