Everyone makes mistakes, everyone learns something new. I figured I would document mine. Probably make this into a weekly series. So let's dive right in.
Lessons learned
1. Rails Routing Concerns.
At work I was tasked with creating a controller that allowed different types of users to edit their details. The controller was pretty straight forward IMO, but the routing is what was tricky. Say we had 2 types of users, the empire and the rebels, what we wanted is that a rebel could go to rebels/info
and edit their details and an empire member could go to empire/info
and edit their details. Typically, one could route them like this
get "/empire/info", to: "/user#edit"
get "/rebels/info", to: "/user#edit"
and that's what I thought of doing. But it's against DRY principles and also there were a lot of scope and namespacing issues based off of how the routes were configured for the project so I dived deep into the docs and I found Routing Concerns
Routing concerns allow you to declare common routes that can be reused inside other resources and routes.
So now what I added to the routes.rb file was this
concerns :info do
get 'info', to '/user#edit'
end
once we have that concern built up, we can use it in a resource like this
resources :empire do
concerns :info
end
resources :rebels do
concerns :info
end
and that solves the routing problem I had.
Routing Concerns!!! Helping you to keep DRY Learn more about concerns
Namespaced controller and url generation gotcha.
This was an interesting one. Let me explain. If you have a controller, say user_controller.rb
and you want to use one of it's methods in a specific namespace that is in no way associated to the user, the way rails will search for the controller might not be what you expect.
Consider the following two blocks of code
1.
resources :avatar do
get '/owner/info', to: 'user#show'
end
2.
resources :avatar do
get '/owner/info', to: '/user#show'
end
The first block will search for the user_controller.rb file in the avatar directory. That is, /avatars/user_controller.rb
. But The user_controller is not going to be there. The second block looks similar except for the fact that there is a leading forward slash before passing the file /user#show
. This will tell rails to override the default and follow that path instead.
This post helped me understand it better.
Mistakes Made
Stimulus Reflex, Typecasting and passing around variables.
I have a form, with which I want to update data through a reflex. I have to pass across some variables to the reflex so it can properly attend to the data being updated. I pass the ID of the object I want to update, and a boolean that will decide some on the fly editing on how the data should be updated. The problem is that boolean. If you call a reflex like this
data: {reflex: "click -> "Post#save", is_edited: true } #true here is a boolean
When the reflex gets the data and you inspect the is_edited
variable, like this
pp "is_edited = #{element.dataset[:is_edited]}" #results in a String
Your logs will return true
But the catch is this, the true
that is returned from the reflex is a string and not a boolean. As such if you try to use it as a boolean, it will always return true, because it is not nil.
This took me a while to figure out because, typically, we pass across ID's of objects and rails does not differentiate between Model.find(1)
and Model.find("1")
(At least not in my experience.) So typecasting has never been something I needed to consider. Not until now.
The solution was simple enough,
is_edited = element.dataset[:is_edited] == true
probably a better way to get back your boolean, but this way I understood exactly what I was checking for.
So now I know to remember that stimulus reflex will type cast the data you send across.
Conclusion
I learned a lot this week. I ended up reading the docs for routing in rails top to bottom. Suffered through some self inflicted Stimulus Reflex errors and learned how to override some defaults in Rails. Pretty exciting week all in all. Cheers.