At Flatiron, every month we learn something completely new that somehow incorporated and compounds what we've learned so far while also telling us to disregard some of the things we struggled to learn. Last month while learning Sinatra, I struggled at first but really came into my stride right before Project Week. It makes sense, if you need a route, you create one; you tell your program exactly what you would like it to do.
Enter Rails and "automagic".
I struggle when I'm not sure why things are happening the way they are. I understand why you wouldn't thrust all of Rails' logic onto someone so green and expect them to succeed but woof. If you check their documentation, creators stress how Rails "Optimizes for programmer happiness with Convention over Configuration," which I know I will benefit from as I continue on my coding journey. In the beginning however, my classmates would suggest a solution to a problem in lecture and I would be left scratching my head. I finally became comfortable with forms but now things are different and have models, and routes are now in the config folder? What? Absolutely insane to me.
Slowly I began to realize the amazing things that Rails makes possible. By using ActiveRecord associations, you're given so many methods you don't have to build out. For example, in my project I have two tables ('characters' and 'campaigns') connected by a join table ('adventures'). With the power of Rails magic I can call my_character_name.campaigns and return an array of their campaigns. All of the hard technical work is done for you, as a user one must simply sort out what you want it to do.
For the most part, relying on RESTful routes makes the project relatively understandable and once you get the hang of things, you can easily create new columns on your table and incorporate them on your views (see above).
I ran into a few issues with my nested route. I wanted a user to be able to create a new character while in one certain campaign. That character would persist and the user could add them to different campaigns, but when they create it, the association to the first campaign is already made. I initially thought I would need to call on the individual instance of the inner join table, something like
adventure = Adventure.new(campaign_id: 1, character_id: 1)
but luckily as I was rewatching lectures at 1.5x speed, I was reminded of the wonderful .build method, and realized I could simply
if @campaign @character = @campaign.characters.build(character_params)
(setting the campaign in a method beforehand)
Which is amazing!
Of course this lead to another problem of the character being created but not immediately being associated with the campaign in the corresponding route (ie /campaigns/campaign_id/characters/new). Word to the wise: .build does not save!
After an embarrassing amount of time, I realized the easiest thing for me to do was just shovel my brand new character into the campaign.characters collection. And that one line of code solved my biggest problem! I understood what the issue was, but I was really struggling with why my solution wasn't working. I tried setting the campaign_id in a hidden field in the new character form (similarly to how I set the user_id to current_user.id), but I knew as I was doing it that it wouldn't work. The character doesn't have a campaign_id, it has many campaigns! So I tried creating a new form for the adventure itself? Foolish. One shovel and everything is where it should be.