You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+186-2Lines changed: 186 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -110,7 +110,7 @@ If any of this is new or confusing information please review Week 2, or simply t
110
110
111
111
Homework: You should have at least one user and one product in your database at this point and time, if you don't please start over from the beginning. You will now run a script that will generate many fake users and many fake products, the technical term for this is "seeding" the database with fake data. We are using a gem called 'ffaker' but you don't need to know that. In the terminal (not the rails console) run this command:
112
112
113
-
$ ruby lib/fake_data.rb
113
+
$ rake fake:data
114
114
115
115
If you got no output at all, check you are in the rails directory by running `ls`
116
116
@@ -472,11 +472,195 @@ Here we are telling our app that the path `/products/new` should map to our prod
472
472
473
473
Now that we've got our Model in place, our Controller, and our Routes for this view file (M_Cr) we need to finish our view before our (MVCr) for this action is complete. Open up `app/views/products/new.html.erb` here we will add a form where a visitor to our website can add a product.
474
474
475
-
In the last homework we added a simple form, we will do the same thing here.
475
+
In the last homework we added a simple form, we will do the same thing here, when a user submits the form the will be adding data to our database, we want the form to use a POST action. We will want to include the name of our product as well as a price. First we will start off by adding the form tags
476
476
477
+
<form method='post' action='/products' >
477
478
479
+
</form>
478
480
481
+
This tells the browser that when we submit this form it will submit to the `/products` path using a method of post. Remember we can re-use the /products path that we used for index, since this is a POST action and index uses a GET. (Routes = URL + HTTP Method). Next we want to add a text field:
Here the type of the input field is "text" and it will be 30 characters wide. When we submit this form we can find the result of this field in the `product[name]`, Rails will translate this to `params[:product][:name]` for us for ease of use. Refresh the page.
Here we are adding an input element with type='submit' which indicates it will be the submit button. We can control the text in the button by change the text inside of it's value. For now it isn't important to memorize the syntax of this html just be able to read it and modify it.
Again we are storing the price inside of the product hash (in rails terms) so we can get to it by using `params[:product][:price]` later. Instead of a text type we are designating this as a number field.
524
+
525
+
526
+
527
+
We've got everything we need to build a product (minus a user which is out of scope for this example). Fill out the form and hit "Create Product" and...
528
+
529
+
530
+
We get another routing error. We only implemented the view for the form, but didn't write any of the logic for persisting (storing) the data to the database. Lets do that now.
531
+
532
+
Open up `config/routes.rb` and add this line:
533
+
534
+
535
+
post '/products' => 'products#create'
536
+
537
+
You will then need to make a new view `create.html.erb` in the folder `app/views/products/` (hopefully, you're noticing a trend), the full path will be `app/views/products/create.html.erb`. Open this file and add this to it:
538
+
539
+
540
+
<h2>Create View</h2>
541
+
542
+
<%= params.inspect %>
543
+
544
+
545
+
Refresh the page, you will be prompted if you are sure. This is a safety feature due to the browser recognizing the POST action. Most POST actions such as ordering an item off of amazon or ebay are intended to happen only once. Refreshing the request could lead to unwanted duplicate orders. For now we haven't written the logic to persist to the database, so click okay.
546
+
547
+
If you accidentally close this page just go back to `/products/new` and re-submit the form.
To create a product. Since params is a hash we can change our view to this
560
+
561
+
<h2>Create View</h2>
562
+
563
+
<%= params[:product].inspect %>
564
+
565
+
Now refresh the page, you should see something like this:
566
+
567
+
{"name"=>"bird house", "price"=>"999"}
568
+
569
+
This looks dangerously close to what we needed to pass to `Product.create` in order to actually save our info to the database. Lets try it out. In the bottom of your view add this line:
570
+
571
+
<%= Product.create(params[:product]).inspect %>
572
+
573
+
Refresh the page, now you should see something like this
If our product has an id, that means it saved. We now have that product in our database. To prove it you can open a `$ rails console` and run this (replacing your id):
578
+
579
+
> Product.where(:id => 225).first
580
+
> #<Product id: 225, user_id: nil, ... >
581
+
582
+
Thats pretty cool, we just built a way to insert data into our database from a website, it might not be pretty but it works!!
583
+
584
+
Refresh the page again, and the product id should be incremented:
But that doesn't seem right now we have two products with duplicate names. Lets tell Rails that shouldn't happen. We'll tell rails to validate the uniqueness of the name field on products. Open your product model
589
+
`app/models/product.rb` and add this code in:
590
+
591
+
validates :name, :uniqueness => true
592
+
593
+
Now refresh the page and the product id is gone! The duplicate product wasn't saved.
Since we told rails that all valid products have a unique name, and rails will only save valid products, this error prevented the product from getting saved. The message tells us why `:name=>["has already been taken"]`, the name has already been taken.
619
+
620
+
Since this is a common occurrence we will need to check for this type of a thing in our code.
621
+
622
+
Rather than use the `create` command in our code we can make a new object and then run save on it (create does both at the same time). Lets remove this line:
623
+
624
+
<% product = Product.create(params[:product]) %>
625
+
626
+
and replace it with this
627
+
628
+
<% product = Product.new(params[:product]) %>
629
+
<%= product.save %>
630
+
631
+
Which essentially does the same thing, but the out put of `product.save` is a boolean (true or false) we can use this to show different message to our user if it saves or not.
632
+
633
+
Add this to your view:
634
+
635
+
<% if product.save %>
636
+
<h2> Congrats You Created a New Product</h2>
637
+
Your product looks like <%= product.inspect %>
638
+
<% else %>
639
+
<h2>Your product was not saved!! </h2>
640
+
<%= product.errors.full_messages %>
641
+
Please go back in your browser and fix the problem
642
+
<% end %>
643
+
644
+
Refresh the page again you should see
645
+
646
+
Your product was not saved!!
647
+
["Name has already been taken"]
648
+
Please go back in your browser and fix the problem
649
+
650
+
Thats much more useful to our user.
651
+
652
+
653
+
Homework:
654
+
655
+
Commit results to git & smile
656
+
657
+
658
+
## Done
659
+
660
+
Congrats, you're done, you've come pretty far since last week. Last week you were barely scratching the surface of generating html with ruby, and now you've completely written half of a CRUD server (for products). Think about that, you took data from a database and brought it to life in the browser. You then turned around and figured out a way to send data from a web form back to your database. That's pretty amazing. We also didn't use much Rails magic, for our models we used vanilla ActiveRecord Ruby objects, for our views we used (mostly) vanilla Ruby ERB. We did use this special Routes thing, and this special controller thing, but not very much.
661
+
662
+
Now that you understand the basics of sending and retrieving data from a database, next week we can start to use some more rails practices to clean up your code and make life a little easier for yourself. If you were curious and decided to poke around in the views and controller for User, you might be a little surprised by how different it is, don't worry most of that is organization and is quite a bit harder to understand without the fundamentals we've just experienced.
663
+
664
+
The most important thing to take away from this MVCr exercise is that you can (and should) build everything incrementally. It's okay to not understand the bigger picture until after you're done. Taking many small steps and checking yourself after each is the best way to stay on course, no matter what the activity is.
0 commit comments