No idea how to start your Rails with Javascript portfolio project? You’re not the only one. I had to watch many videos and read many articles before I could begin my project. One of the blogs I read was Christina Williams’ (which by the way inspired me to write this blog. Thank you, Christina!) and it tremendously helped me and a few others I know. I must say that making the project itself helped me understand Javascript more.
Project Walkthrough
Here are the steps I took for my Rails with JS project:
1. Meet up with your project section coach
I set up a meeting with the current JavaScript Project Section Coach, Dalia Sawaya, and she was very helpful in making me understand what the project requires. She also explained:
Javascript Model Object = Javascript version of a Ruby Object
Prototype Function = an instance method in Ruby
Constructor Function = Initialize in Ruby
Additionally, she recommended the following videos:
Debugging in Chrome Dev Tools with JS
I would also recommend you watch this Rails JS study group by Brad Smith.
2. Duplicate your Rails project (optional)
Although I think I could have just continued my Rails project or create a branch, I decided to make a duplicate of that project instead.
- Create a new repository - in my case, I named it
family-friendly-travel-guide-js
- Duplicate Rails project repo by following these steps
3. Add these gems to your Gemfile
gem 'jquery-rails'
gem 'active_model_serializers'
Tip: Don’t forget to bundle install. Also, I read that turbolinks
doesn’t go well with jquery-rails
. I don’t know exactly why but when I removed it from my Gemfile and application.js, my project ran more smoothly and it stopped me from frequently refreshing my index because it used to not render via JSON right away.
4. Require directives to the application.js file
application.js
//= require jquery
//= require rails-ujs
//= require bootstrap-sprockets
//= require activestorage
//= require guides
//= require_tree .
//= require guides
is my guides.js
file. If needed, reread the Javascript Manifests Lesson
5. Add Serializer
I only added one serializer file to my serializer folder. Run rails g serializer filename
serializers/guide_serializer.rb
class GuideSerializer < ActiveModel::Serializer
attributes :id, :title, :summary, :lodging, :itinerary, :destination_location, :airport, :baby_gear_rental, :park, :zoo, :restaurant, :luggage_storage
belongs_to :destination
has_many :ratings
end
6. Render JSON
I put JSON to my index
, create
, and show
methods in my guides_controller.rb
file. To know that it’s working, go to your localhost:3000/index.json or localhost:3000/index/id.json
INDEX
def index
if !params[:destination_id].blank?
@destination_id = Destination.find_by(id: params[:destination_id]).id
@guides = Guide.where(destination_id: @destination_id)
else
@guides = Guide.all
** respond_to do |f|
f.html {render :index}
f.json {render json: @guides}
end**
end
end
CREATE
def create
@guide = current_user.guides.build(guide_params)
@guide.user_id = current_user.id
if @guide.save
** render json: @guide**
else
flash[:message] = "#{@guide.errors.full_messages.to_sentence}."
render :new
end
end
SHOW
def show
** respond_to do |f|
f.html {render :show}
f.json {render json: @guide}
end**
end
7. Start coding in your JS file
Although I had to make some changes to my layout, views, and other files, I spent more time coding in my guides.js file. Following along the videos I mentioned above really helped me finish this project.
guides.js
$(document).ready(function() {
// console.log('hello')
guidesIndexClick()
showGuide()
newForm()
})
function guidesIndexClick() {
$('.all-guides').on('click', (e) => {
e.preventDefault()
// console.log('hello again')
history.pushState(null, null, 'guides')
fetch('/guides.json')
.then(response => response.json())
.then(guides => {
$('.container').html('')
guides.forEach(guide => {
// console.log(guide)
let newGuide = new Guide(guide)
let guideHtml = newGuide.formatIndex()
// console.log(guideHtml)
$('.container').append(guideHtml)
// console.log(newGuide)
})
})
})
}
function showGuide() {
$(document).on('click', '.show_guide', function(e) {
e.preventDefault()
$('.container').html('')
let id = $(this).attr('data-id')
fetch(`/guides/${id}.json`)
.then(response => response.json())
.then(guide => {
let newGuide = new Guide(guide)
let guideHtml = newGuide.formatShow()
$('.container').append(guideHtml)
})
})
}
function newForm() {
$(document).on('submit', '#new_guide', function(e) {
e.preventDefault()
console.log('event preventend')
const values = $(this).serialize()
$.post('/guides', values).done(function(data) {
$('.container').html('')
const newGuide = new Guide(data)
const guideHtmlToAdd = newGuide.formatShow()
$('.container').html(guideHtmlToAdd)
})
})
}
function Guide(guide) {
this.id = guide.id
this.title = guide.title
this.destination_location = guide.destination_location
this.summary = guide.summary
this.airport = guide.airport
this.lodging = guide.lodging
this.restaurant = guide.restaurant
this.park = guide.park
this.zoo = guide.zoo
this.baby_gear_rental = guide.baby_gear_rental
this.luggage_storage = guide.luggage_storage
this.itinerary = guide.itinerary
}
Guide.prototype.formatIndex = function() {
console.log(this)
let guideHtml = `
<div class="col-md-4">
<a href="/guides/${this.id}" data-id="${this.id}" class="show_guide"><h2 class="guide-title">${this.title}</h2></a>
<p class="guide-destination">${this.destination_location}</p>
</div>
`
return guideHtml
}
Guide.prototype.formatShow = function() {
console.log(this)
let guideHtml = `
<div class="col-md-12">
<h3>${this.title}</h3>
<p class="guide-destination"> <i class="fas fa-globe-americas"></i> ${this.destination_location}</p>
</div>
<div class="col-md-6">
<p class="guide-summary"> ${this.summary}</p>
<hr class="my-4">
<h2 class="guide-destination">Itinerary</h2>
<p><i class="fas fa-map-signs"></i> ${this.itinerary}</p>
</div>
<div class="col-md-6">
<h2 class="guide-destination">Details</h2>
<p><i class="fas fa-plane-departure"></i> ${this.airport}</p>
<p><i class="fas fa-bed"></i> ${this.lodging}</p>
<p><i class="fas fa-utensils"></i> ${this.restaurant}</p>
<p><i class="fas fa-tree"></i> ${this.park}</p>
<p><i class="fas fa-hippo"></i> ${this.zoo}</p><br>
<h2 class="guide-destination">Nearby</h2>
</div>
<div class="col-md-3">
<h2 class="guide-destination"><i class="fas fa-baby-carriage"></i> Baby Gear Rental: ${this.baby_gear_rental}</h2>
</div>
<div class="col-md-3">
<h2 class="guide-destination"><i class="fas fa-suitcase-rolling"></i> Luggage Storage: ${this.luggage_storage}</h2>
</div>
`
return guideHtml
}
I wanted my images to show just like in my Rails project but I don’t know how at the moment. I realized that it’s more important to understand and finish this project first, and I can always go back and improve it at a later time.
RAILS PROJECT SCREENSHOTS
More tips (more like learn from my mistakes)
- don’t forget to use back ticks when needed
- know the difference between .container and #container
- don’t forget your } brackets
Hope this can help other students who are about to do their Rails with JS projects. Can’t wait to start React!