<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Douglas Berkley</title>
    <description>The latest articles on DEV Community by Douglas Berkley (@dmbf29).</description>
    <link>https://dev.to/dmbf29</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F688628%2Fd6f8ddd0-8caa-41ce-9e2b-6dd4ab82c6e2.jpeg</url>
      <title>DEV Community: Douglas Berkley</title>
      <link>https://dev.to/dmbf29</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dmbf29"/>
    <language>en</language>
    <item>
      <title>How to use nested attributes in Ruby on Rails (create multiple objects at once)</title>
      <dc:creator>Douglas Berkley</dc:creator>
      <pubDate>Wed, 23 Jul 2025 06:22:14 +0000</pubDate>
      <link>https://dev.to/dmbf29/how-to-use-nested-attributes-in-ruby-on-rails-create-multiple-objects-at-once-4jle</link>
      <guid>https://dev.to/dmbf29/how-to-use-nested-attributes-in-ruby-on-rails-create-multiple-objects-at-once-4jle</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Quite often in my applications, I want to create multiples types of objects in one form submission. For example, when one instance is created, you want the associations to be created a the same time. Everything I do here is based on &lt;a href="https://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html" rel="noopener noreferrer"&gt;the official documentation.&lt;/a&gt; I'm going to move forward using this database schema:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4ejkr9dqy59o13domtz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4ejkr9dqy59o13domtz.png" alt=" " width="598" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see here, I have one &lt;code&gt;group&lt;/code&gt; (with a &lt;code&gt;name&lt;/code&gt;) which &lt;code&gt;has_many :people&lt;/code&gt;. One &lt;code&gt;person&lt;/code&gt; that &lt;code&gt;belongs_to :group&lt;/code&gt;. If I follow regular Rails CRUD actions, I would have to create a group then follow up with creating the people in this group separately. It might look something like this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvjyphuufc546iu7frbxe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvjyphuufc546iu7frbxe.png" alt=" " width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So how can I create both a &lt;code&gt;group&lt;/code&gt; but also &lt;code&gt;people&lt;/code&gt; at the same time?&lt;/p&gt;
&lt;h1&gt;
  
  
  Form Setup
&lt;/h1&gt;

&lt;p&gt;I would love my form to look something more like this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu31pkkhlnvzqi9ow00vy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu31pkkhlnvzqi9ow00vy.png" alt=" " width="800" height="525"&gt;&lt;/a&gt;&lt;br&gt;
This allows me to create a &lt;code&gt;group&lt;/code&gt; with the &lt;code&gt;name&lt;/code&gt; but then also add &lt;code&gt;people&lt;/code&gt;, which has &lt;code&gt;first_name&lt;/code&gt; and &lt;code&gt;last_name&lt;/code&gt;, into that group.&lt;/p&gt;

&lt;p&gt;I'm using the gem &lt;a href="https://github.com/heartcombo/simple_form" rel="noopener noreferrer"&gt;Simple Form&lt;/a&gt; for my forms. So the original form would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;simple_form_for&lt;/span&gt; &lt;span class="vi"&gt;@group&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'The Berkleys'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt; &lt;span class="s1"&gt;'Submit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s1"&gt;'btn btn-primary mt-3'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This needs two things in order to work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create the &lt;code&gt;@group&lt;/code&gt; instance variable in your controller#action&lt;/li&gt;
&lt;li&gt;Add the route to create a &lt;code&gt;group&lt;/code&gt; in your &lt;code&gt;routes.rb&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But this obviously only allows me to create a group. We want to add the people into this form. For this, we're going to use &lt;a href="https://github.com/heartcombo/simple_form?tab=readme-ov-file#simple-fields-for" rel="noopener noreferrer"&gt;simple_fields_for&lt;/a&gt; to build a &lt;em&gt;form within a form&lt;/em&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Nested Form
&lt;/h1&gt;

&lt;p&gt;To add a &lt;code&gt;person&lt;/code&gt; in our app, we would normally have a form like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;simple_form_for&lt;/span&gt; &lt;span class="vi"&gt;@person&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'John'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'Doe'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt; &lt;span class="s1"&gt;'Submit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s1"&gt;'btn btn-primary mt-3'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the idea here is to move the &lt;code&gt;person&lt;/code&gt; form into our &lt;code&gt;group&lt;/code&gt; form. This is where our &lt;code&gt;simple_fields_for&lt;/code&gt; comes into play. Our nested form will looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;simple_form_for&lt;/span&gt; &lt;span class="vi"&gt;@group&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- Anything a group would have --&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'The Berkleys'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- The nested form --&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;simple_fields_for&lt;/span&gt; &lt;span class="ss"&gt;:people&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;person_form&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"d-flex align-items-center w-100"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="c"&gt;&amp;lt;!-- Anything a person would have --&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;person_form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'John'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;person_form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'John'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt; &lt;span class="s1"&gt;'Submit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s1"&gt;'btn btn-primary mt-3'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This doesn't just work by default though. We have three more steps to get this setup work:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tell our &lt;code&gt;group&lt;/code&gt; model that we'll be creating people along with the group&lt;/li&gt;
&lt;li&gt;Define objects in the controller so our form helper can build the form.&lt;/li&gt;
&lt;li&gt;Update the strong parameters since we're sending more information from the form.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Update the Model
&lt;/h1&gt;

&lt;p&gt;Let's go into our &lt;code&gt;group.rb&lt;/code&gt; to tell our model that we'll also be creating people at the same time. &lt;code&gt;accepts_nested_attributes_for&lt;/code&gt; comes from &lt;a href="https://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html" rel="noopener noreferrer"&gt;the docs&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# group.rb (model)&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:people&lt;/span&gt;
&lt;span class="n"&gt;accepts_nested_attributes_for&lt;/span&gt; &lt;span class="ss"&gt;:people&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;allow_destroy: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Update the Controller
&lt;/h1&gt;

&lt;p&gt;So normally in our &lt;code&gt;new&lt;/code&gt; action, we create an empty instance variable to give to our form helper.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="vi"&gt;@group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But because we're also creating &lt;code&gt;people&lt;/code&gt; at the same time, we need to set this up in our controller too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="vi"&gt;@group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="vi"&gt;@group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;people&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt; &lt;span class="c1"&gt;# needed for nested form&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What is the &lt;code&gt;@group.people.build&lt;/code&gt; doing?
&lt;/h3&gt;

&lt;p&gt;It is used to initialize a new &lt;code&gt;person&lt;/code&gt; object associated with the &lt;code&gt;@group&lt;/code&gt; instance. The &lt;code&gt;build&lt;/code&gt; method in Active Record (when used on an association like &lt;code&gt;@group.people&lt;/code&gt;) creates a new associated &lt;code&gt;person&lt;/code&gt; object in memory without saving it to the database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is the &lt;code&gt;@group.people.build&lt;/code&gt; needed?
&lt;/h3&gt;

&lt;p&gt;Our nested form expects at least one &lt;code&gt;person&lt;/code&gt; object to exist so that it can generate the input fields for &lt;code&gt;first_name&lt;/code&gt; and &lt;code&gt;last_name&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Update the Strong Params
&lt;/h1&gt;

&lt;p&gt;Now that we're creating two things at once, it's still only getting sent to the original form location. In our example, it's getting sent to the &lt;code&gt;groups#create&lt;/code&gt; action. We actually don't need to change how a group gets created. It could potentially looks like this (and notice that there is nothing about a &lt;code&gt;person&lt;/code&gt; in here):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
  &lt;span class="vi"&gt;@group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="vi"&gt;@group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current_user&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;
    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;group_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;groups_path&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See? Nothing about &lt;code&gt;people&lt;/code&gt;. But we will have to change one thing, and that's our strong parameters. Basically we told our &lt;code&gt;group&lt;/code&gt; model that we'd also be passing people into it. So let's take a look a the parameters that got sent from the form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"group"&lt;/span&gt;&lt;span class="err"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="err"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"The Berkleys"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="s2"&gt;"people_attributes"&lt;/span&gt;&lt;span class="err"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="err"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"first_name"&lt;/span&gt;&lt;span class="err"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"Douglas"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"last_name"&lt;/span&gt;&lt;span class="err"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"Berkley"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The params looks a bit strange, right? It's normal to see our &lt;code&gt;"group"=&amp;gt; { "name"=&amp;gt;"The Berkleys" }"&lt;/code&gt; but the &lt;code&gt;people_attributes&lt;/code&gt; is new from our from our nested form and &lt;code&gt;accepts_nested_attributes_for&lt;/code&gt;. There's a &lt;code&gt;0&lt;/code&gt; in the &lt;code&gt;people_attributes&lt;/code&gt; from the form because in theory, we can now create as many people as we want for the one group inside the form.&lt;/p&gt;

&lt;p&gt;So now let's update our strong parameters to accept &lt;code&gt;people_attributes&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;group_params&lt;/span&gt;
  &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:group&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;permit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;people_attributes: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:last_name&lt;/span&gt; &lt;span class="ss"&gt;:_destroy&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our form should be good to go!&lt;/p&gt;

&lt;h1&gt;
  
  
  Going further...
&lt;/h1&gt;

&lt;p&gt;What if I want to create more than one &lt;code&gt;person&lt;/code&gt; at a time? As of now, our nested form just has one option for our &lt;code&gt;person&lt;/code&gt; (just one &lt;code&gt;first_name&lt;/code&gt; and &lt;code&gt;last_name&lt;/code&gt; input). I could hard-code it by just copying and pasting our nested part in our form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;simple_form_for&lt;/span&gt; &lt;span class="vi"&gt;@group&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- Anything a group would have --&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'The Berkleys'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- FIRST PERSON --&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;simple_fields_for&lt;/span&gt; &lt;span class="ss"&gt;:people&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;person_form&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"d-flex align-items-center w-100"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="c"&gt;&amp;lt;!-- Anything a person would have --&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;person_form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'John'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;person_form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'John'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- SECOND PERSON --&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;simple_fields_for&lt;/span&gt; &lt;span class="ss"&gt;:people&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;person_form&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"d-flex align-items-center w-100"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="c"&gt;&amp;lt;!-- Anything a person would have --&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;person_form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'John'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;person_form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'John'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt; &lt;span class="s1"&gt;'Submit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s1"&gt;'btn btn-primary mt-3'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is fine if we know exactly how many people I want to add when I create a group. But it would be much better if it was dynamic. For example, I can add 1 person or 10 people.&lt;br&gt;
To make it dynamic, it can be a bit tricky. So I like to use the &lt;a href="https://www.stimulus-components.com/docs/stimulus-rails-nested-form" rel="noopener noreferrer"&gt;Stimulus component&lt;/a&gt; which simplifies the process. &lt;/p&gt;
&lt;h3&gt;
  
  
  Import the component
&lt;/h3&gt;

&lt;p&gt;Check if you're using &lt;code&gt;importmap&lt;/code&gt; or &lt;code&gt;yarn&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;importmap pin @stimulus-components/rails-nested-form
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>rails</category>
    </item>
    <item>
      <title>How to use nested attributes in Ruby on Rails (create associated objects in one form)</title>
      <dc:creator>Douglas Berkley</dc:creator>
      <pubDate>Tue, 25 Feb 2025 07:21:28 +0000</pubDate>
      <link>https://dev.to/dmbf29/how-to-use-nested-attributes-in-ruby-on-rails-create-multiple-objects-at-once-3m67</link>
      <guid>https://dev.to/dmbf29/how-to-use-nested-attributes-in-ruby-on-rails-create-multiple-objects-at-once-3m67</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Quite often in my applications, I want to create multiple types of objects in one form submission. For example, when one instance is created, you want the associations to be created at the same time. Everything I do here is based on &lt;a href="https://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html" rel="noopener noreferrer"&gt;the official documentation.&lt;/a&gt; I'm going to move forward using this database schema:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4ejkr9dqy59o13domtz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4ejkr9dqy59o13domtz.png" alt="database schema" width="598" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see here, I have one &lt;code&gt;group&lt;/code&gt; (with a &lt;code&gt;name&lt;/code&gt;) which &lt;code&gt;has_many :people&lt;/code&gt;. One &lt;code&gt;person&lt;/code&gt; that &lt;code&gt;belongs_to :group&lt;/code&gt;. If I follow regular Rails CRUD actions, I would have to create a group then follow up with creating the people in this group separately. It might look something like this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvjyphuufc546iu7frbxe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvjyphuufc546iu7frbxe.png" alt="nested form example" width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So how can I create both a &lt;code&gt;group&lt;/code&gt; but also &lt;code&gt;people&lt;/code&gt; at the same time?&lt;/p&gt;
&lt;h2&gt;
  
  
  Form Setup
&lt;/h2&gt;

&lt;p&gt;I would love my form to look more like this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu31pkkhlnvzqi9ow00vy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu31pkkhlnvzqi9ow00vy.png" alt="simple form example" width="800" height="525"&gt;&lt;/a&gt;&lt;br&gt;
This allows me to create a &lt;code&gt;group&lt;/code&gt; with the &lt;code&gt;name&lt;/code&gt; but then also add &lt;code&gt;people&lt;/code&gt;, which has &lt;code&gt;first_name&lt;/code&gt; and &lt;code&gt;last_name&lt;/code&gt;, into that group.&lt;/p&gt;

&lt;p&gt;I'm using the gem &lt;a href="https://github.com/heartcombo/simple_form" rel="noopener noreferrer"&gt;Simple Form&lt;/a&gt; for my forms. So the original form would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;simple_form_for&lt;/span&gt; &lt;span class="vi"&gt;@group&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'The Berkleys'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt; &lt;span class="s1"&gt;'Submit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s1"&gt;'btn btn-primary mt-3'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This needs two things in order to work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create the &lt;code&gt;@group&lt;/code&gt; instance variable in your controller#action&lt;/li&gt;
&lt;li&gt;Add the route to create a &lt;code&gt;group&lt;/code&gt; in your &lt;code&gt;routes.rb&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But this obviously only allows me to create a group. We want to add the people into this form. For this, we're going to use &lt;a href="https://github.com/heartcombo/simple_form?tab=readme-ov-file#simple-fields-for" rel="noopener noreferrer"&gt;simple_fields_for&lt;/a&gt; to build a &lt;em&gt;form within a form&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nested Form
&lt;/h2&gt;

&lt;p&gt;To add a &lt;code&gt;person&lt;/code&gt; in our app, we would normally have a form like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;simple_form_for&lt;/span&gt; &lt;span class="vi"&gt;@person&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'John'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'Doe'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt; &lt;span class="s1"&gt;'Submit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s1"&gt;'btn btn-primary mt-3'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the idea here is to move the &lt;code&gt;person&lt;/code&gt; form into our &lt;code&gt;group&lt;/code&gt; form. This is where our &lt;code&gt;simple_fields_for&lt;/code&gt; comes into play. Our nested form will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;simple_form_for&lt;/span&gt; &lt;span class="vi"&gt;@group&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- Anything a group would have --&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'The Berkleys'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- The nested form --&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;simple_fields_for&lt;/span&gt; &lt;span class="ss"&gt;:people&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;person_form&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"d-flex align-items-center w-100"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="c"&gt;&amp;lt;!-- Anything a person would have --&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;person_form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'John'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;person_form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'John'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt; &lt;span class="s1"&gt;'Submit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s1"&gt;'btn btn-primary mt-3'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This doesn't just work by default, though. We have three more steps to get this setup working:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tell our &lt;code&gt;group&lt;/code&gt; model that we'll be creating people along with the group&lt;/li&gt;
&lt;li&gt;Define an object in the controller so our form helper can build it.&lt;/li&gt;
&lt;li&gt;Update the strong parameters since we're sending more information from the form.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Update the Model
&lt;/h2&gt;

&lt;p&gt;Let's go into our &lt;code&gt;group.rb&lt;/code&gt; to tell our model that we'll also be creating people at the same time. &lt;code&gt;accepts_nested_attributes_for&lt;/code&gt; comes from &lt;a href="https://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html" rel="noopener noreferrer"&gt;the docs&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# group.rb (model)&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:people&lt;/span&gt;
&lt;span class="n"&gt;accepts_nested_attributes_for&lt;/span&gt; &lt;span class="ss"&gt;:people&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;allow_destroy: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Update the Controller
&lt;/h2&gt;

&lt;p&gt;So normally in our &lt;code&gt;new&lt;/code&gt; action, we create an empty instance variable to give to our form helper.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="vi"&gt;@group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But because we're also creating &lt;code&gt;people&lt;/code&gt; at the same time, we need to set this up in our controller too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="vi"&gt;@group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="vi"&gt;@group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;people&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt; &lt;span class="c1"&gt;# needed for nested form&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What is the &lt;code&gt;@group.people.build&lt;/code&gt; doing?
&lt;/h3&gt;

&lt;p&gt;It is used to initialize a new &lt;code&gt;person&lt;/code&gt; object associated with the &lt;code&gt;@group&lt;/code&gt; instance. The &lt;code&gt;build&lt;/code&gt; method in Active Record (when used on an association like &lt;code&gt;@group.people&lt;/code&gt;) creates a new associated &lt;code&gt;person&lt;/code&gt; object in memory without saving it to the database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is the &lt;code&gt;@group.people.build&lt;/code&gt; needed?
&lt;/h3&gt;

&lt;p&gt;Our nested form expects at least one &lt;code&gt;person&lt;/code&gt; object to exist, so that it can generate the input fields for &lt;code&gt;first_name&lt;/code&gt; and &lt;code&gt;last_name&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update the Strong Params
&lt;/h2&gt;

&lt;p&gt;Now that we're creating two things at once, it's still only getting sent to the original form location. In our example, it's getting sent to the &lt;code&gt;groups#create&lt;/code&gt; action. We actually don't need to change how a group gets created. It could potentially look like this (and notice that there is nothing about a &lt;code&gt;person&lt;/code&gt; in here):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
  &lt;span class="vi"&gt;@group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="vi"&gt;@group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;current_user&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;
    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;group_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;groups_path&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See? Nothing about &lt;code&gt;people&lt;/code&gt;. But we will have to change one thing, and that's our strong parameters. Basically we told our &lt;code&gt;group&lt;/code&gt; model that we'd also be passing people into it. So let's take a look at the parameters that got sent from the form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"group"&lt;/span&gt;&lt;span class="err"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="err"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"The Berkleys"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="s2"&gt;"people_attributes"&lt;/span&gt;&lt;span class="err"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="err"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"first_name"&lt;/span&gt;&lt;span class="err"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"Douglas"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"last_name"&lt;/span&gt;&lt;span class="err"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="s2"&gt;"Berkley"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The params looks a bit strange, right? It's normal to see our &lt;code&gt;"group"=&amp;gt; { "name"=&amp;gt;"The Berkleys" }"&lt;/code&gt; but the &lt;code&gt;people_attributes&lt;/code&gt; is new from our nested form and &lt;code&gt;accepts_nested_attributes_for&lt;/code&gt;. There's a &lt;code&gt;0&lt;/code&gt; in the &lt;code&gt;people_attributes&lt;/code&gt; from the form because in theory, we can now create as many people as we want for the one group inside the form.&lt;/p&gt;

&lt;p&gt;So now let's update our strong parameters to accept &lt;code&gt;:people_attributes&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;group_params&lt;/span&gt;
  &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:group&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;permit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;people_attributes: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:_destroy&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our form should be good to go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Going further...
&lt;/h2&gt;

&lt;p&gt;What if I want to create more than one &lt;code&gt;person&lt;/code&gt; at a time? As of now, our nested form just has one option for our &lt;code&gt;person&lt;/code&gt; (just one &lt;code&gt;first_name&lt;/code&gt; and &lt;code&gt;last_name&lt;/code&gt; input). I could hard-code it by just copying and pasting our nested part in our form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;simple_form_for&lt;/span&gt; &lt;span class="vi"&gt;@group&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- Anything a group would have --&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'The Berkleys'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- FIRST PERSON --&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;simple_fields_for&lt;/span&gt; &lt;span class="ss"&gt;:people&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;person_form&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"d-flex align-items-center w-100"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="c"&gt;&amp;lt;!-- Anything a person would have --&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;person_form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'John'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;person_form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'John'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- SECOND PERSON --&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;simple_fields_for&lt;/span&gt; &lt;span class="ss"&gt;:people&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;person_form&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"d-flex align-items-center w-100"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="c"&gt;&amp;lt;!-- Anything a person would have --&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;person_form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'John'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
      &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;person_form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt; &lt;span class="ss"&gt;:last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;placeholder: &lt;/span&gt;&lt;span class="s1"&gt;'John'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt; &lt;span class="s1"&gt;'Submit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s1"&gt;'btn btn-primary mt-3'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is fine if we know exactly how many people I want to add when I create a group. But it would be much better if it was dynamic. For example, I can add 1 person or 10 people.&lt;br&gt;
To make it dynamic, it can be a bit tricky. So I like to use the &lt;a href="https://www.stimulus-components.com/docs/stimulus-rails-nested-form" rel="noopener noreferrer"&gt;Rails Nested Form - Stimulus component&lt;/a&gt; which simplifies the process. I'll let you follow the other tutorial to solve that issue, but in the end, we could have a nice dynamic form that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fplt4v01lvsjhbx1zmelo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fplt4v01lvsjhbx1zmelo.png" alt="final form screenshot" width="800" height="787"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>rails</category>
    </item>
    <item>
      <title>Update total booking price on a form (like Airbnb) without refreshing using Stimulus</title>
      <dc:creator>Douglas Berkley</dc:creator>
      <pubDate>Thu, 05 Oct 2023 07:45:13 +0000</pubDate>
      <link>https://dev.to/dmbf29/update-total-booking-price-on-a-form-like-airbnb-without-refreshing-using-stimulus-25m5</link>
      <guid>https://dev.to/dmbf29/update-total-booking-price-on-a-form-like-airbnb-without-refreshing-using-stimulus-25m5</guid>
      <description>&lt;p&gt;At &lt;a href="https://www.lewagon.com/tokyo" rel="noopener noreferrer"&gt;Le Wagon&lt;/a&gt;, our students spend 1 week building a Ruby on Rails(v7) Airbnb clone. There are times where we want to update booking prices in real-time for a user based on the dates they choose. &lt;/p&gt;

&lt;h3&gt;
  
  
  Airbnb Example
&lt;/h3&gt;

&lt;p&gt;Let's base our idea on the booking form from Airbnb. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbnawtc4p9df870sl18v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbnawtc4p9df870sl18v.png" alt="Airbnb booking form for 3 days"&gt;&lt;/a&gt;&lt;br&gt;
Airbnb is telling us how much it costs to book a specific place per night, but it's also doing the math for the entire 3-day stay.&lt;br&gt;
So if I want to add two extra days to my trip, I'd like to have the form update the final price as soon as I change the dates. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe3ae6jhlcodx541bweu1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe3ae6jhlcodx541bweu1.png" alt="Airbnb booking form for 5 days"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;Let's walk through how we can do this in Ruby on Rails(v7) and Stimulus.&lt;/p&gt;

&lt;p&gt;In our example here, we're booking a home. So our &lt;code&gt;booking&lt;/code&gt;  has a &lt;code&gt;start_date&lt;/code&gt;, &lt;code&gt;end_date&lt;/code&gt;, and the &lt;code&gt;home&lt;/code&gt; has a &lt;code&gt;price&lt;/code&gt; (per night).&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffthdtrarl0rdkg962iyc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffthdtrarl0rdkg962iyc.png" alt="Schema for homes"&gt;&lt;/a&gt;&lt;br&gt;
When we're building our form (using &lt;a href="https://github.com/heartcombo/simple_form" rel="noopener noreferrer"&gt;Simple Form&lt;/a&gt; and &lt;a href="https://getbootstrap.com/docs/5.2/getting-started/introduction/" rel="noopener noreferrer"&gt;Bootstrap 5.2&lt;/a&gt;), we'll try to replicate the same idea as the Airbnb form.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5542a0dhpevoba32kab6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5542a0dhpevoba32kab6.png" alt="Our booking form"&gt;&lt;/a&gt;&lt;br&gt;
Then when our user chooses the dates, we want to calculate and display the total amount&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd5gjwc1w95z5q4e9upyj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd5gjwc1w95z5q4e9upyj.png" alt="Our booking form"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay so let's get this feature installed and plugged into our app. We'll do this in two steps: the Stimulus controller and HTML(erb) form.&lt;/p&gt;
&lt;h3&gt;
  
  
  Stimulus controller
&lt;/h3&gt;

&lt;p&gt;Let's generate our Stimulus controller first in the Terminal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails g stimulus booking_price
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we can add in the logic to calculate the days and prices&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// booking_price_controller.js

import { Controller } from "@hotwired/stimulus";

// Connects to data-controller="booking-price"
export default class extends Controller {
  static targets = ["start_date", "end_date", "price", "info"];
  static values = { price: Number };

  update() {
    const pricePerDay = parseInt(this.priceValue, 10);
    // make sure the user has chosen a start date and end date
    if (
      this.start_dateTarget.value !== "" &amp;amp;&amp;amp;
      this.end_dateTarget.value !== ""
    ) {
      // calculating the time from the values in the HTML
      const diffInMs =
        new Date(this.end_dateTarget.value) -
        new Date(this.start_dateTarget.value);
      const diffInDays = diffInMs / (1000 * 60 * 60 * 24);
      if (diffInDays &amp;gt; 0) {
        // displays the total price per nigh
        this.infoTarget.innerText = `¥${pricePerDay} x ${diffInDays} nights`;
        this.priceTarget.innerHTML = `&amp;lt;span&amp;gt;¥${(
          diffInDays * pricePerDay
        ).toLocaleString()}&amp;lt;/span&amp;gt; &amp;lt;small class='fw-light'&amp;gt;total&amp;lt;/small&amp;gt; `;
      } else if (diffInDays === 0) {
        // displays 1-night minimum if end date is same as start date
        this.infoTarget.innerText = "";
        this.priceTarget.innerHTML =
          "&amp;lt;span class='text-danger fw-light'&amp;gt;1-night mininum&amp;lt;/span&amp;gt;";
      } else {
        // displays invalid if the end date is before the start or not overnight
        this.infoTarget.innerText = "";
        this.priceTarget.innerHTML =
          "&amp;lt;span class='text-danger fw-light'&amp;gt;Invalid dates&amp;lt;/span&amp;gt;";
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  View
&lt;/h3&gt;

&lt;p&gt;Then let's head to our view, where we have a number of things to add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We are wrapping the entire form in our &lt;code&gt;data-controller="booking-price"&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;We're adding our price as a &lt;code&gt;data-booking-price-price-value="&amp;lt;%= @home.price %&amp;gt;"&lt;/code&gt; so that we have access to it in the JS Controller. &lt;/li&gt;
&lt;li&gt;We're adding data-actions onto our form inputs so that when the user changes the dates, it'll update our price.&lt;/li&gt;
&lt;li&gt;We're adding a target at the end where we'd like to display the total price once it's been calculated.&lt;/li&gt;
&lt;li&gt;Lots of style with Bootstrap.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div data-controller="booking-price" data-booking-price-price-value="&amp;lt;%= @home.price %&amp;gt;" class="mt-5 border p-3 rounded"&amp;gt;
  &amp;lt;!-- Displays price/night on top of form --&amp;gt;
  &amp;lt;p class='fw-bold fs-3'&amp;gt;¥&amp;lt;%= @home.price %&amp;gt; &amp;lt;small class='fw-light'&amp;gt;night&amp;lt;/small&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;%= simple_form_for [@home, @booking] do |f| %&amp;gt;
    &amp;lt;div class="d-flex"&amp;gt;
      &amp;lt;!-- On change of dates, it triggers our update inside of our JS controller --&amp;gt;
      &amp;lt;%= f.input :start_date, html5: true, input_html: { data: { booking_price_target: 'start_date', action: 'change-&amp;gt;booking-price#update' }, min: Date.today } %&amp;gt;
      &amp;lt;%= f.input :end_date, html5: true, input_html: { data: { booking_price_target: 'end_date', action: 'change-&amp;gt;booking-price#update' }, min: Date.today } %&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;%= f.submit 'Book', class: 'btn btn-primary w-100' %&amp;gt;
    &amp;lt;!-- Hidden when no dates chosen, total amount displayed here when changed --&amp;gt;
    &amp;lt;p class='mt-3 d-flex align-items-center justify-content-between'&amp;gt;
      &amp;lt;span data-booking-price-target='info'&amp;gt;&amp;lt;/span&amp;gt;
      &amp;lt;span class='fw-bold' data-booking-price-target='price'&amp;gt;&amp;lt;/span&amp;gt;
    &amp;lt;/p&amp;gt;
  &amp;lt;% end %&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voilà! And now you should be be able to give your user a better date picking experience.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>rails</category>
      <category>stimulus</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Active Record Scopes Tutorial - Rails - Booking example</title>
      <dc:creator>Douglas Berkley</dc:creator>
      <pubDate>Wed, 04 Oct 2023 06:31:07 +0000</pubDate>
      <link>https://dev.to/dmbf29/active-record-scopes-rails-booking-example-3oo0</link>
      <guid>https://dev.to/dmbf29/active-record-scopes-rails-booking-example-3oo0</guid>
      <description>&lt;p&gt;At &lt;a href="https://lewagon.com/tokyo"&gt;Le Wagon&lt;/a&gt;, our students spend 1 week building a Ruby on Rails Airbnb clone. We normally end up with a schema relatively close to this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oulCoBsA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mpebhk277l52h58jpm96.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oulCoBsA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mpebhk277l52h58jpm96.png" alt="DB Schema example" width="800" height="568"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we get to the bookings page, it can be tricky how to retrieve all of the relevant bookings for a particular user. An empty bookings page example (with &lt;a href="https://dev.to/dmbf29/building-functional-tabs-with-style-pdb"&gt;tabs&lt;/a&gt;)&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LqAqMQgo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gmvsf9cb5uk2qgjh8foz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LqAqMQgo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gmvsf9cb5uk2qgjh8foz.png" alt="Bookings page example" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we use &lt;code&gt;Booking.all&lt;/code&gt;, this will give us all of the bookings for every user in the entire application which is obviously not what we want. The simple version of this would just to get all of the bookings for the person logged in (if you're using &lt;a href="https://github.com/heartcombo/devise"&gt;Devise&lt;/a&gt;) &lt;code&gt;current_user.bookings&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;However, you may have noticed that on our &lt;code&gt;booking&lt;/code&gt;, we have a &lt;code&gt;start_date&lt;/code&gt;, &lt;code&gt;end_date&lt;/code&gt;, and &lt;code&gt;status&lt;/code&gt;. So our bookings become a little bit more complicated. Do we want all of our &lt;code&gt;pending&lt;/code&gt; bookings? Bookings that are in the future? Bookings that are currently happening? Well when we use &lt;code&gt;current_user.bookings&lt;/code&gt;, it's giving us everything.&lt;/p&gt;

&lt;p&gt;To be able to sort through all the different types of bookings that we have, we can use &lt;a href="https://guides.rubyonrails.org/active_record_querying.html#scopes"&gt;Active Record scopes&lt;/a&gt;. If you haven't dealt with scopes before, the syntax might feel a bit strange. Here is one example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# booking.rb (model)
scope :past, -&amp;gt; { where('end_date &amp;lt; ?', Date.today) }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives us access to method &lt;code&gt;.past&lt;/code&gt; now. So in our controller, we could use &lt;code&gt;Booking.past&lt;/code&gt; if we want past bookings from all users. But in this particular example, now we can access all the past bookings for a particular user: &lt;code&gt;current_user.bookings.past&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So given this one example of a scope, we could now go crazy with lot of different types of bookings (depending on how we're using them in the view). Our model might end up looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Booking &amp;lt; ApplicationRecord
  belongs_to :user
  belongs_to :offer
  validates :start_date, presence: true
  validates :end_date, presence: true
  enum status: { pending: 0, accepted: 1, rejected: 2 }

  scope :past, -&amp;gt; { where('end_date &amp;lt; ?', Date.today) }
  scope :future, -&amp;gt; { where('start_date &amp;gt; ?', Date.today) }
  scope :active, -&amp;gt; { where('start_date &amp;lt; ? AND end_date &amp;gt; ?', Date.today, Date.today) }
  scope :today, -&amp;gt; { accepted.where(date: Date.today) }
  scope :upcoming, -&amp;gt; { accepted.future }
  scope :need_response, -&amp;gt; { pending.future }
  scope :expired, -&amp;gt; { pending.past }
  scope :completed, -&amp;gt; { accepted.past }
  scope :not_rejected, -&amp;gt; { where.not(status: :rejected) }

  def number_of_days
    (start_date - end_date).to_i 
  end

  def price
    offer.price * number_of_days
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now thinking about our how to use this, we can load all of the user's bookings in the bookings controller.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def index
  @bookings = current_user.bookings
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in our view we can display whatever type of bookings that we decided, using our newly made scopes!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;%= render 'cards', bookings: @bookings.today %&amp;gt;
&amp;lt;%= render 'cards', bookings: @bookings.future %&amp;gt;
&amp;lt;%= render 'cards', bookings: @bookings.active %&amp;gt;
&amp;lt;%= render 'cards', bookings: @bookings.need_response %&amp;gt;
&amp;lt;%= render 'cards', bookings: @bookings.past %&amp;gt;
&amp;lt;!-- etc. --&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>rails</category>
      <category>ruby</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Building Functional Tabs with Style</title>
      <dc:creator>Douglas Berkley</dc:creator>
      <pubDate>Wed, 01 Feb 2023 05:42:25 +0000</pubDate>
      <link>https://dev.to/dmbf29/building-functional-tabs-with-style-pdb</link>
      <guid>https://dev.to/dmbf29/building-functional-tabs-with-style-pdb</guid>
      <description>&lt;p&gt;&lt;em&gt;How to combine &lt;a href="https://getbootstrap.com/docs/5.2/getting-started/introduction" rel="noopener noreferrer"&gt;Bootstrap 5.2&lt;/a&gt; function with style&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There's no reason to reinvent the wheel here. The tabs that Bootstrap provide for us give us all of the functionality that we need. You can give them a nice click-around &lt;a href="https://getbootstrap.com/docs/5.2/components/navs-tabs/#javascript-behavior" rel="noopener noreferrer"&gt;here&lt;/a&gt; or just take a look at the screenshot below 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feyb18seywoqitv84p8f9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feyb18seywoqitv84p8f9.png" alt="Bootstrap tabs screenshot" width="800" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The problem is that they don't look very nice. Thankfully the kind developers at Le Wagon have provided us with some tab style in their &lt;a href="https://uikit.lewagon.com/documentation#tabs" rel="noopener noreferrer"&gt;UI Kit&lt;/a&gt;. But, they are not functional just yet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgushn5rebrxujb9bu3w3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgushn5rebrxujb9bu3w3.png" alt="Le Wagon tabs screenshot" width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So with the combination of Bootstrap functionality and Le Wagon style, we've come up with this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffov4l69532yec2tak7v6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffov4l69532yec2tak7v6.png" alt="Bootstrap tabs with Le Wagon style screenshot" width="800" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can have a look at the code and click around on this &lt;a href="https://codepen.io/dmbf29/pen/mdjzZQz" rel="noopener noreferrer"&gt;Codepen&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  SCSS
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Remember to import both CSS and JS from Bootstrap as well.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.tabs-underlined {
  display: flex;
  align-items: center;
}
.tabs-underlined {
  .tab-underlined {
    color: black;
    padding: 8px;
    margin: 8px 16px;
    opacity: .4;
    cursor: pointer;
    text-decoration: none;
    border-bottom: 4px solid transparent;
    display: block;
  }
  .tab-underlined:hover {
    opacity: 0.5;
  }
  .tab-underlined.active {
    opacity: 1;
    border-bottom: 3px solid #555555;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  HTML
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ul class="nav tabs-underlined" id="myTab" role="tablist"&amp;gt;
  &amp;lt;li class="nav-item" role="presentation"&amp;gt;
    &amp;lt;span class="nav-link tab-underlined active" id="bookings-tab" data-bs-toggle="tab" data-bs-target="#bookings-tab-pane" role="tab" aria-controls="bookings-tab-pane" aria-selected="true"&amp;gt;Bookings&amp;lt;/span&amp;gt;
  &amp;lt;/li&amp;gt;
  &amp;lt;li class="nav-item" role="presentation"&amp;gt;
    &amp;lt;span class="nav-link tab-underlined" id="requests-tab" data-bs-toggle="tab" data-bs-target="#requests-tab-pane" role="tab" aria-controls="requests-tab-pane" aria-selected="false"&amp;gt;Requests&amp;lt;/span&amp;gt;
  &amp;lt;/li&amp;gt;
  &amp;lt;li class="nav-item" role="presentation"&amp;gt;
    &amp;lt;span class="nav-link tab-underlined" id="conversations-tab" data-bs-toggle="tab" data-bs-target="#conversations-tab-pane" role="tab" aria-controls="conversations-tab-pane" aria-selected="false"&amp;gt;Conversations&amp;lt;/span&amp;gt;
  &amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&amp;lt;div class="tab-content" id="myTabContent"&amp;gt;
  &amp;lt;div class="tab-pane fade py-3 show active" id="bookings-tab-pane" role="tabpanel" aria-labelledby="bookings-tab" tabindex="0"&amp;gt;
    This is the content for the Bookings tab. Notice in the tab HTML there is a href="#bookings". This is pointing to the id of this div..
  &amp;lt;/div&amp;gt;
  &amp;lt;div class="tab-pane fade py-3" id="requests-tab-pane" role="tabpanel" aria-labelledby="requests-tab" tabindex="0"&amp;gt;
    This is the content for the Requests tab. Notice in the tab HTML there is a href="#requests". This is pointing to the id of this div..
  &amp;lt;/div&amp;gt;
  &amp;lt;div class="tab-pane fade py-3" id="conversations-tab-pane" role="tabpanel" aria-labelledby="conversations-tab" tabindex="0"&amp;gt;
    This is the content for the Conversations tab. Notice in the tab HTML there is a href="#converstations". This is pointing to the id of this div.
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>crypto</category>
      <category>cryptocurrency</category>
      <category>web3</category>
    </item>
    <item>
      <title>Make a Card Clickable in CSS</title>
      <dc:creator>Douglas Berkley</dc:creator>
      <pubDate>Wed, 07 Dec 2022 01:58:41 +0000</pubDate>
      <link>https://dev.to/dmbf29/make-a-card-clickable-in-css-10fo</link>
      <guid>https://dev.to/dmbf29/make-a-card-clickable-in-css-10fo</guid>
      <description>&lt;p&gt;On the surface, this one seems straight forward: a grid of clickable cards, easy right? Well as you may have seen when we use an anchor tag, it comes with some default styling we don't necessary want.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhhkios5xcq6wa3zb8wpf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhhkios5xcq6wa3zb8wpf.png" alt="Image description" width="364" height="54"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Start
&lt;/h2&gt;

&lt;p&gt;First, let's get a good looking card we can use. Let's take this one from the &lt;a href="https://uikit.lewagon.com/documentation#card_product" rel="noopener noreferrer"&gt;Le Wagon UI Kit&lt;/a&gt;.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F81d7zekwdvntfzof5om1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F81d7zekwdvntfzof5om1.png" alt="Card" width="800" height="315"&gt;&lt;/a&gt;&lt;br&gt;
Looks sharp, right? But let's see what happens when we wrap the same code inside of an anchor tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;a href="#"&amp;gt;
  &amp;lt;!-- card html --&amp;gt;
&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or the Rails way...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;%= link_to card_path do %&amp;gt;
  &amp;lt;!-- card html --&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8x3tk9numdaaaegomnnf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8x3tk9numdaaaegomnnf.png" alt="Image description" width="800" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;This just ruined all of our style. We can click on it, but all the text had that &lt;code&gt;text-underline&lt;/code&gt; and unfortunate blue. So, let's take a step back and take a different approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;This might seem strange at first, but we're not going to wrap the card in the link. We're going three dimensional here. We're going to place the link over the card.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First&lt;/strong&gt;: we build a link &lt;strong&gt;inside of our card&lt;/strong&gt; with no text inside of our link to display. Let's also create a new class called card-link&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;a href="#" class='card-link'&amp;gt;&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or the Rails way...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;%= link_to '', card_path, class: 'card-link'  %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Second&lt;/strong&gt;: we make our card &lt;code&gt;position: relative&lt;/code&gt;, then we can make our link &lt;code&gt;position: absolute&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Third&lt;/strong&gt;: we stretch the link over the entirety of the card. Our link won't take up an space, so we have to give it some special css attributes. Pin it to the corners then stretch over the entire width like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;top: 0;
bottom: 0;
left: 0;
width: 100%;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have a clickable card that looks like our original&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F81d7zekwdvntfzof5om1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F81d7zekwdvntfzof5om1.png" alt="Card" width="800" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  CSS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.card-trip {
  overflow: hidden;
  background: white;
  box-shadow: 0 0 15px rgba(0,0,0,0.2);
  position: relative; // NEEDED FOR THE LINK
}

.card-trip &amp;gt; img {
  height: 200px;
  width: 100%;
  object-fit: cover;
}

.card-trip h2 {
  font-size: 16px;
  font-weight: bold;
  margin: 0;
}

.card-trip p {
  font-size: 12px;
  opacity: .7;
  margin: 0;
}

.card-trip .card-trip-infos {
  padding: 16px;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  position: relative;
}

.card-trip-infos .card-trip-user {
  position: absolute;
  right: 16px;
  top: -20px;
  width: 40px;
}

// To stretch the link on top of the card div
.card-link {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 100%;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The ERB Way
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="card-trip"&amp;gt;
  &amp;lt;%= image_tag "https://raw.githubusercontent.com/lewagon/fullstack-images/master/uikit/greece.jpg" %&amp;gt;
  &amp;lt;div class="card-trip-infos"&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;h2&amp;gt;Title here&amp;lt;/h2&amp;gt;
      &amp;lt;p&amp;gt;Short description here!&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;h2 class="card-trip-pricing"&amp;gt;£99.99&amp;lt;/h2&amp;gt;
    &amp;lt;%= image_tag "https://kitt.lewagon.com/placeholder/users/dmbf29", class: "card-trip-user avatar-bordered" %&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;%= link_to '', card_path(element), class: 'card-link'  %&amp;gt;
  &amp;lt;!-- You need to replace card_path with your appropriate route  --&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Pure HTML way
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="card-trip"&amp;gt;
  &amp;lt;img src="https://raw.githubusercontent.com/lewagon/fullstack-images/master/uikit/greece.jpg" /&amp;gt;
  &amp;lt;div class="card-trip-infos"&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;h2&amp;gt;Title here&amp;lt;/h2&amp;gt;
      &amp;lt;p&amp;gt;Short description here!&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;h2 class="card-trip-pricing"&amp;gt;£99.99&amp;lt;/h2&amp;gt;
    &amp;lt;img src="https://kitt.lewagon.com/placeholder/users/dmbf29" class="card-trip-user avatar-bordered" /&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;a href="#" class='card-link'&amp;gt;&amp;lt;/a&amp;gt;
  &amp;lt;!-- You need to replace the href # with your appropriate route --&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Updating a Booking Status in Rails</title>
      <dc:creator>Douglas Berkley</dc:creator>
      <pubDate>Wed, 07 Dec 2022 01:51:54 +0000</pubDate>
      <link>https://dev.to/dmbf29/updating-a-booking-status-2ihh</link>
      <guid>https://dev.to/dmbf29/updating-a-booking-status-2ihh</guid>
      <description>&lt;p&gt;When building an Airbnb clone app, we often have a &lt;code&gt;booking&lt;/code&gt; model in our application.(And hopefully you have a default status.). It should look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---shAvwQi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ko6jz4gw4wo10ro00qzw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---shAvwQi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ko6jz4gw4wo10ro00qzw.png" alt="Image description" width="294" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Really the only thing we're interested here is how to change the status to &lt;code&gt;accepted&lt;/code&gt; or &lt;code&gt;rejected&lt;/code&gt; as the owner of the offer. An AirBnb host isn't going to accept every offer that comes through. So how does this work? Do we create buttons? Links? Separate controller actions for accept and reject? No. I've seen a lot of different ways people try to solve this, but it's best to keep it simple.&lt;/p&gt;

&lt;p&gt;We need a form. This form is just going to &lt;code&gt;update&lt;/code&gt; our booking. This allows our &lt;code&gt;bookings#update&lt;/code&gt; controller action to handle both the accepting and rejecting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup the Route
&lt;/h2&gt;

&lt;p&gt;Let's make sure we have the correct route in our &lt;code&gt;routes.rb&lt;/code&gt;. This shouldn't be nested since the bookings already have an ID.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# routes.rb
resources :bookings, only: [:update]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure the Controller
&lt;/h2&gt;

&lt;p&gt;Let's add the update action in the &lt;code&gt;bookings&lt;/code&gt; controller (along with the strong params if they're missing). This is just standard CRUD, nothing special here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# bookings_controller.rb
def update
  @booking = Booking.find(params[:id])
  if @booking.update(booking_params)
    # redirect_to # up to you...
  else
    # render # where was the booking update form?
  end
end

private

def booking_params
  # TODO: check your model, might be different than mine
  params.require(:booking).permit(:status, :start_time, :end_time)
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Build your View
&lt;/h2&gt;

&lt;p&gt;Now to the tough part. Let's go to your view where you want to accept and reject. This can be a couple places depending on how you build your routes.&lt;/p&gt;

&lt;p&gt;I'm going to make another assumption here. You're either iterating over &lt;code&gt;@bookings&lt;/code&gt; or something like &lt;code&gt;current_user.bookings_as_owner&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;% @bookings.each do |booking| %&amp;gt;
  &amp;lt;!-- with the booking card here --&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can design your cards how you see it fit with your application. But I'll let's just use a simple one to get started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qBAZVpJM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rlgopstn9bkrfrgizkz4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qBAZVpJM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rlgopstn9bkrfrgizkz4.png" alt="Image description" width="880" height="246"&gt;&lt;/a&gt;&lt;br&gt;
Okay now for those "buttons". We don't want just a normal button or link though. This is where we need the booking update form. Let's use simple_form_for (&lt;a href="https://github.com/heartcombo/simple_form"&gt;check out the docs here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;We're going to need two forms for each action. And we're going to hide the new status as a hidden field. The "button" is going to be the submit for the form. Like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="d-flex"&amp;gt;
  &amp;lt;%= simple_form_for booking do |f| %&amp;gt;
    &amp;lt;%= f.input :status, as: :hidden, input_html: { value: 'accepted'} %&amp;gt;
    &amp;lt;%= f.submit 'Accept', class: 'btn btn-info' %&amp;gt;
  &amp;lt;% end %&amp;gt;

  &amp;lt;%= simple_form_for booking do |f| %&amp;gt;
    &amp;lt;%= f.input :status, as: :hidden, input_html: { value: 'rejected'} %&amp;gt;
    &amp;lt;%= f.submit 'Reject', class: 'btn btn-light' %&amp;gt;
  &amp;lt;% end %&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Status Conditional
&lt;/h2&gt;

&lt;p&gt;If your booking status is &lt;code&gt;pending&lt;/code&gt; then we'll show the forms. Otherwise, we'll display the status.&lt;/p&gt;

&lt;p&gt;Let's create a method in our model.&lt;br&gt;
⚠️ If you are using status as an &lt;code&gt;enum&lt;/code&gt;, you don't need this. You already have this method available.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# booking.rb (model)
def pending?
  status == 'pending'
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can use that method in our conditional&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;% if booking.pending? %&amp;gt;
  &amp;lt;!-- Display Forms--&amp;gt;
&amp;lt;% else %&amp;gt;
  &amp;lt;!-- Display Status--&amp;gt;
  &amp;lt;p class='booking-tag'&amp;gt;&amp;lt;%= booking.status %&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We should get some bookings like this now:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BnCg2cOj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tmlt4brsp2l45rxrcelj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BnCg2cOj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tmlt4brsp2l45rxrcelj.png" alt="Image description" width="880" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap Up
&lt;/h2&gt;

&lt;p&gt;Now all we have to do is build these forms in our iteration.&lt;/p&gt;

&lt;h3&gt;
  
  
  ERB
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="bookings"&amp;gt;
  &amp;lt;% @bookings.each do |booking| %&amp;gt;
    &amp;lt;div class="booking"&amp;gt;
      &amp;lt;div class='booking-left'&amp;gt;
        &amp;lt;!-- if you're using cloudinary and activestorage --&amp;gt;
        &amp;lt;%= cl_image_tag booking.user.photo, class: 'avatar-bordered' %&amp;gt;
        &amp;lt;div class="booking-info"&amp;gt;
          &amp;lt;div class="booking-info-title"&amp;gt;
            &amp;lt;%= booking.user.name %&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;div class="booking-info-details"&amp;gt;
            &amp;lt;%= booking.start_time.strftime('%l:%M %p') %&amp;gt; - &amp;lt;%= booking.end_time.strftime('%l:%M %p') %&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div class="booking-actions"&amp;gt;
        &amp;lt;% if booking.pending? %&amp;gt;
          &amp;lt;%= simple_form_for booking do |f| %&amp;gt;
            &amp;lt;%= f.input :status, as: :hidden, input_html: { value: 'accepted'} %&amp;gt;
            &amp;lt;%= f.submit 'Accept', class: 'btn btn-info' %&amp;gt;
          &amp;lt;% end %&amp;gt;
          &amp;lt;%= simple_form_for booking do |f| %&amp;gt;
            &amp;lt;%= f.input :status, as: :hidden, input_html: { value: 'rejected'} %&amp;gt;
            &amp;lt;%= f.submit 'Reject', class: 'btn btn-light' %&amp;gt;
          &amp;lt;% end %&amp;gt;
        &amp;lt;% else %&amp;gt;
          &amp;lt;p class='booking-tag'&amp;gt;&amp;lt;%= booking.status %&amp;gt;&amp;lt;/p&amp;gt;
        &amp;lt;% end %&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;% end %&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CSS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.booking {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 16px 0;

  .booking-left {
    display: flex;
    align-items: center;
  }

  .booking-actions {
    display: flex;
    align-items: center;
  }
  .booking-tag {
    margin: 1px 4px;
    padding: 2px 5px 0px 5px;
    background-color: #bfbfbf;
    color: white;
    border-radius: 8px;
    font-weight: lighter;
    font-size: 12px;
  }
}

.booking-info {
  display: flex;
  flex-direction: column;
  margin-left: 8px;

  .booking-info-title {
    font-weight: bolder;
    font-size: 1.2em;
  }

  .booking-info-details {
    font-weight: lighter;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>rails</category>
      <category>css</category>
    </item>
    <item>
      <title>Seeding Users with Photos in Rails</title>
      <dc:creator>Douglas Berkley</dc:creator>
      <pubDate>Wed, 07 Dec 2022 01:27:13 +0000</pubDate>
      <link>https://dev.to/dmbf29/seeding-users-with-photos-157j</link>
      <guid>https://dev.to/dmbf29/seeding-users-with-photos-157j</guid>
      <description>&lt;p&gt;When starting a new project, adding seeds gives life to your application. It gives you some initial data to play around with and adding users is normally an integral part of it. They tricky part is that we want it to feel real without actually using people's photos or information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Faker
&lt;/h2&gt;

&lt;p&gt;I'm going to assume that we're using Devise for our User model. That means we'll most likely be logging in with an email. Let's use the gem &lt;a href="https://github.com/faker-ruby/faker" rel="noopener noreferrer"&gt;Faker&lt;/a&gt;, but you have to be careful with this one. Some of their emails are real. The last thing you want to do is accidentally email all of those &lt;code&gt;@gmail.com&lt;/code&gt; addresses you seeded into your database.&lt;/p&gt;

&lt;p&gt;If you use &lt;code&gt;Faker::Internet.safe_email&lt;/code&gt;, then it'll guarantee you're using an email address that can't receive messages (ie: &lt;code&gt;margert_huel@example.net&lt;/code&gt;). To counteract the &lt;code&gt;@example.com&lt;/code&gt;, I like to use the real emails of the other members in my team. This allows them to always know an email they can sign in with. Otherwise every time you run your seeds, you'll have to open the Rails console and find a new users's email.&lt;/p&gt;

&lt;p&gt;Don't forget to add the gem into your &lt;code&gt;Gemfile&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gem 'faker', :git =&amp;gt; 'https://github.com/faker-ruby/faker.git', :branch =&amp;gt; 'main'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you've added the new gem, you need to make sure it's installed. From your Terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bundle install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Attaching a Photo
&lt;/h2&gt;

&lt;p&gt;We need to go inside our User model first (&lt;code&gt;user.rb&lt;/code&gt;) and attach a photo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ...
has_one_attached :photo
# ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Take this as an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require "open-uri" # at the top

article = Article.new(title: 'NES', body: "A great console")
file = URI.open('https://giantbomb1.cbsistatic.com/uploads/original/9/99864/2419866-nes_console_set.png')
article.photo.attach(io: file, filename: 'nes.png', content_type: 'image/png')

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But, that's only one photo on one instance of an &lt;code&gt;article&lt;/code&gt;. How can we generate a unique photo for each user that we seed in the database? We can user &lt;a href="https://this-person-does-not-exist.com/en" rel="noopener noreferrer"&gt;this-person-does-not-exist.com&lt;/a&gt;. This website uses AI to generate photos of fake people.&lt;/p&gt;

&lt;p&gt;So let's attach those AI photos to our users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require 'open-uri'
require 'nokogiri'

50.times do
  user = User.create!(
  email: Faker::Internet.safe_email,
  password: '123123', # needs to be 6 digits,
  # add any additional attributes you have on your model
)
  # gender options: 'all' or 'male' or 'female'
  gender = 'male'
  # age options: 'all' or '12-18' or '19-25' or '26-35' or '35-50' or '50+'
  age = '19-25'
  # ethnicity options: 'all' or 'asian' or 'white' or 'black' or 'indian' or 'middle_eastern' or 'latino_hispanic'
  ethnicity = 'all'

  url = "https://this-person-does-not-exist.com/new?gender=#{gender}&amp;amp;age=#{age}&amp;amp;etnic=#{ethnicity}"
  json = URI.open(url).string
  src = JSON.parse(json)['src']
  photo_url = "https://this-person-does-not-exist.com#{src}"
  file = URI.open(photo_url)
  user.photo.attach(io: file, filename: 'user.png', content_type: 'image/png')
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Make Sure They Attached
&lt;/h2&gt;

&lt;p&gt;Go to your Terminal and open up a rails c&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pull up the last user and make sure a photo is attached&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User.last.photo.attached? # if true, success!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
  </channel>
</rss>
