Creating Feature in our Rails blog App to Add Article and Enable Reviews
Ok as part of this effort and series to create a blog, lets have our front end work with the newest technology. Hence we will use React Js as our front end and rails as our backend.
Let Create our model:
Rails g Model Article name image_url slug
Rails g Model Review title description score:integer article:belongs_to
If we go into Model we will see our model article and review model.
class Article < ApplicationRecord
has_many :reviews
before_create :slugify
def slugify
self.slug = name.parameterize
end
def avg_score
reviews.average(:score).round(2).to_f
end
end
Review Model
class Review < ApplicationRecord
belongs_to :article
end
If you Jump to db migrate folder you will see rails create 2 migration for us. Rails uses active model which tightly couple our models with structure of our database.
Run
Rail db:migrate
Add has_many relationship
has_many :reviews
Let set the slug for our database before we create it in our database.
What is Slugify? well let explain
Let go to rails console.
rails c
If we have
"Hello Khemlall".parameterized
It will change the structure to lower case and hyphenated.
Lets seed some data: Go to Seeds → db → Migrate
articles = Article.create([
{
name: "How to c#",
image_url: "https://www.motc.gov.qa/sites/default/files/c-programming.png"
},
{
name: "pictures of nature",
image_url: "https://thumbs.dreamstime.com/z/scenic-nature-landscape-path-near-lake-forest-path-tunnel-trees-near-lake-scenic-nature-autumn-landscape-panorama-view-115358410.jpg"
}
])reviews = Review.create([
{
title: 'Great article',
description: 'i learn something new',
score: 5,
article: articles.first},
{
title: 'Wow Great article i love it!',
description: 'i learn something new',
score: 5,
article: articles.first}])
Then we need to go back to console and run the following
rails db:seed
Now lets test that everything is working
article = Article.first
Article Load (0.2ms) SELECT "articles".* FROM "articles" ORDER BY "articles"."id" ASC LIMIT ? [["LIMIT", 1]]
=> #<Article id: 1, name: "How to c#", image_url: "https://www.motc.gov.qa/sites/default/files/c-prog...", slug: "how-to-c", created_at: "2021-02-28 22:51:45.357842000 +0000", updated_at: "20...
Article Load (0.2ms) SELECT "articles".* FROM "articles" ORDER BY "articles"."id" ASC LIMIT ? [["LIMIT", 1]]
=> #<Article id: 1, name: "How to c#", image_url: "https://www.motc.gov.qa/sites/default/files/c-prog...", slug: "how-to-c", created_at: "2021-02-28 22:51:45.357842000 +0000", updated_at: "20...
3.0.0 :009 > article.slug
Article Load (0.2ms) SELECT "articles".* FROM "articles" ORDER BY "articles"."id" ASC LIMIT ? [["LIMIT", 1]]
=> #<Article id: 1, name: "How to c#", image_url: "https://www.motc.gov.qa/sites/default/files/c-prog...", slug: "how-to-c", created_at: "2021-02-28 22:51:45.357842000 +0000", updated_at: "20...
3.0.0 :009 > article.slug=> "how-to-c"
article.reviews
Review Load (0.3ms) SELECT "reviews".* FROM "reviews" WHERE "reviews"."article_id" = ? /* loading for inspect */ LIMIT ? [["article_id", 1], ["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Review id: 1, title: "Great article", description: "i learn something new", score: 5, article_id: 1, created_at: "2021-02-28 22:51:45.439789000 +0000", updated_at: "2021-02-28 22:51:45.439789000 +0000">, #<Review id: 2, title: "Wow Great article i love it!", description: "i learn something new", score: 5, article_id: 1, created_at: "2021-02-28 22:51:45.456268000 +0000", updated_at: "2021-02-28 22:51:45.456268000 +0000">]>
3.0.0 :011 > article.reviews.count
(0.3ms) SELECT COUNT(*) FROM "reviews" WHERE "reviews"."article_id" = ? [["article_id", 1]]
=> 2
Now lets Create Api using Fast json api gem. open Gemfile and add the following
gem ‘fast_jsonapi’
Then run bundle
Let now create a serializer for these two model
rails g serializer Article name image_url slug
This will create a article_serializer in the following place:
app/serializers/article_serializer.rb
let do the same for Review
rails g serializer Review title description score article_id
it should create the following here:
app/serializers/review_serializer.rb
Article Serializer
class ArticleSerializer
include FastJsonapi::ObjectSerializer
attributes :name, :image_url, :slug
has_many :reviews
end
Review Serializer
class ReviewSerializer
include FastJsonapi::ObjectSerializer
attributes :title, :description, :score, :article_id
end
Lets test out this in our Raisl console.
rails c
Say we have our first article
article = Article.first
Now let create a new instance of our article serializer
ArtitleSerializer.new(article)
results
.0.0 :003 > ArticleSerializer.new(article)
=> #<ArticleSerializer:0x00000000064e11e0 @fieldsets={}, @params={}, @resource=#<Article id: 1, name: "How to c#", image_url: "https://www.motc.gov.qa/sites/default/files/c-prog...", slug: "how-to-c", created_at: "2021-02-28 22:51:45.357842000 +0000", updated_at: "2021-02-28 22:51:45.357842000 +0000">>
3.0.0 :004 > ArticleSerializer.new(article).seroa;ozed_json
ArticleSerializer.new(article).serialized_json
ArticleSerializer.new(article).serialized_json
(0.2ms) SELECT "reviews"."id" FROM "reviews" WHERE "reviews"."article_id" = ? [["article_id", 1]]
=> "{\"data\":{\"id\":\"1\",\"type\":\"article\",\"attributes\":{\"name\":\"How to c#\",\"image_url\":\"https://www.motc.gov.qa/sites/default/files/c-programming.png\",\"slug\":\"how-to-c\"},\"relationships\":{\"reviews\":{\"data\":[{\"id\":\"1\",\"type\":\"review\"},{\"id\":\"2\",\"type\":\"review\"}]}}}}"