This commit is contained in:
João Victor Geonizeli
2022-02-27 17:02:37 -03:00
parent 53c7d35d74
commit 1d692b31f8
13 changed files with 258 additions and 3 deletions

View File

@@ -0,0 +1,53 @@
class PostsController < ApplicationController
before_action :set_post, only: %i[ show update destroy ]
# GET /posts
# GET /posts.json
def index
@posts = Post.all
end
# GET /posts/1
# GET /posts/1.json
def show
end
# POST /posts
# POST /posts.json
def create
@post = Post.new(post_params)
if @post.save
render :show, status: :created, location: @post
else
render json: @post.errors, status: :unprocessable_entity
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
if @post.update(post_params)
render :show, status: :ok, location: @post
else
render json: @post.errors, status: :unprocessable_entity
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
@post.destroy
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
@post = Post.find(params[:id])
end
# Only allow a list of trusted parameters through.
def post_params
params.require(:post).permit(:content, :user_id, :quoted_post_id)
end
end

27
app/models/post.rb Normal file
View File

@@ -0,0 +1,27 @@
class Post < ApplicationRecord
belongs_to :user
belongs_to :quoted_post, optional: true, class_name: 'Post'
validates :content, length: { maximum: 777 }
validates :content, presence: true, if: :quoted_post?
def kind
if quoted_post?
:quoted_post
elsif repost?
:repost
else
:post
end
end
private
def quoted_post?
content.present? && quoted_post_id
end
def repost?
content.blank? && quoted_post_id
end
end

View File

@@ -0,0 +1,4 @@
json.extract! post, :id, :content, :user_id, :created_at, :updated_at
json.url post_url(post, format: :json)
json.quoted_post(post.quoted_post)

View File

@@ -0,0 +1 @@
json.array! @posts, partial: "posts/post", as: :post

View File

@@ -0,0 +1 @@
json.partial! "posts/post", post: @post

View File

@@ -1,6 +1,5 @@
Rails.application.routes.draw do Rails.application.routes.draw do
resources :posts, only: [:index, :show, :create]
resources :user_follows, only: [:create, :destroy] resources :user_follows, only: [:create, :destroy]
resources :users, only: [:show] resources :users, only: [:show]
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
end end

View File

@@ -0,0 +1,11 @@
class CreatePosts < ActiveRecord::Migration[7.0]
def change
create_table :posts do |t|
t.text :content, null: true
t.references :user, null: false, references: :user, foreign_key: { to_table: :users }
t.references :quoted_post, null: true, references: :post, foreign_key: { to_table: :posts }
t.timestamps
end
end
end

14
db/schema.rb generated
View File

@@ -10,10 +10,20 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2022_02_27_175028) do ActiveRecord::Schema[7.0].define(version: 2022_02_27_194054) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
create_table "posts", force: :cascade do |t|
t.text "content"
t.bigint "user_id", null: false
t.bigint "quoted_post_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["quoted_post_id"], name: "index_posts_on_quoted_post_id"
t.index ["user_id"], name: "index_posts_on_user_id"
end
create_table "user_follows", force: :cascade do |t| create_table "user_follows", force: :cascade do |t|
t.bigint "follower_id" t.bigint "follower_id"
t.bigint "followed_id" t.bigint "followed_id"
@@ -30,6 +40,8 @@ ActiveRecord::Schema[7.0].define(version: 2022_02_27_175028) do
t.index ["username"], name: "index_users_on_username" t.index ["username"], name: "index_users_on_username"
end end
add_foreign_key "posts", "posts", column: "quoted_post_id"
add_foreign_key "posts", "users"
add_foreign_key "user_follows", "users", column: "followed_id" add_foreign_key "user_follows", "users", column: "followed_id"
add_foreign_key "user_follows", "users", column: "follower_id" add_foreign_key "user_follows", "users", column: "follower_id"
end end

View File

@@ -4,3 +4,6 @@ geonizeli = User.find_or_create_by(username: 'geonizeli')
UserFollow.find_or_create_by(follower_id: xpto.id, followed_id: geonizeli.id) UserFollow.find_or_create_by(follower_id: xpto.id, followed_id: geonizeli.id)
UserFollow.find_or_create_by(follower_id: geonizeli.id, followed_id: xpto.id) UserFollow.find_or_create_by(follower_id: geonizeli.id, followed_id: xpto.id)
first_post = Post.find_or_create_by(content: 'Hello World!', user_id: xpto.id)
Post.find_or_create_by(content: 'Hello World!', user_id: xpto.id, quoted_post_id: first_post.id)

7
spec/factories/posts.rb Normal file
View File

@@ -0,0 +1,7 @@
FactoryBot.define do
factory :post do
content { Faker::Lorem.paragraph }
user
quoted_post { nil }
end
end

31
spec/models/post_spec.rb Normal file
View File

@@ -0,0 +1,31 @@
require 'rails_helper'
RSpec.describe Post, type: :model do
describe '#kind' do
context 'when post have other post reference and a content' do
it 'returns :quoted_post' do
quoted_post = create(:post)
post = create(:post, quoted_post: quoted_post)
expect(post.kind).to eq(:quoted_post)
end
end
context 'when post have other post reference and dont have a content' do
it 'returns :repost' do
quoted_post = create(:post)
post = create(:post, quoted_post: quoted_post, content: nil)
expect(post.kind).to eq(:repost)
end
end
context 'when post dont have other post reference and have a content' do
it 'returns :post' do
post = create(:post)
expect(post.kind).to eq(:post)
end
end
end
end

View File

@@ -0,0 +1,88 @@
require 'rails_helper'
# This spec was generated by rspec-rails when you ran the scaffold generator.
# It demonstrates how one might use RSpec to test the controller code that
# was generated by Rails when you ran the scaffold generator.
#
# It assumes that the implementation code is generated by the rails scaffold
# generator. If you are using any extension libraries to generate different
# controller code, this generated spec may or may not pass.
#
# It only uses APIs available in rails and/or rspec-rails. There are a number
# of tools you can use to make these specs even more expressive, but we're
# sticking to rails and rspec-rails APIs to keep things simple and stable.
RSpec.describe "/posts", type: :request do
let(:quoted_post) { create(:post) }
let(:valid_attributes) {
{
content: "Quo dolorem recusandae. Vero laborum deleniti. Qui ipsam illum.",
user_id: create(:user).id,
}
}
let(:invalid_attributes) {
{
content: "Quo dolorem recusandae. Vero laborum deleniti. Qui ipsam illum."
}
}
# This should return the minimal set of values that should be in the headers
# in order to pass any filters (e.g. authentication) defined in
# PostsController, or in your router and rack
# middleware. Be sure to keep this updated too.
let(:valid_headers) {
{}
}
describe "GET /index" do
it "renders a successful response" do
Post.create! valid_attributes
get posts_url, headers: valid_headers, as: :json
expect(response).to be_successful
end
end
describe "GET /show" do
it "renders a successful response" do
post = Post.create! valid_attributes
get post_url(post), as: :json
expect(response).to be_successful
end
end
describe "POST /create" do
context "with valid parameters" do
it "creates a new Post" do
expect {
post posts_url,
params: { post: valid_attributes }, headers: valid_headers, as: :json
}.to change(Post, :count).by(1)
end
it "renders a JSON response with the new post" do
post posts_url,
params: { post: valid_attributes }, headers: valid_headers, as: :json
expect(response).to have_http_status(:created)
expect(response.content_type).to match(a_string_including("application/json"))
end
end
context "with invalid parameters" do
it "does not create a new Post" do
expect {
post posts_url,
params: { post: invalid_attributes }, as: :json
}.to change(Post, :count).by(0)
end
it "renders a JSON response with errors for the new post" do
post posts_url,
params: { post: invalid_attributes }, headers: valid_headers, as: :json
expect(response).to have_http_status(:unprocessable_entity)
expect(response.content_type).to match(a_string_including("application/json"))
end
end
end
end

View File

@@ -0,0 +1,18 @@
require "rails_helper"
RSpec.describe PostsController, type: :routing do
describe "routing" do
it "routes to #index" do
expect(get: "/posts").to route_to("posts#index")
end
it "routes to #show" do
expect(get: "/posts/1").to route_to("posts#show", id: "1")
end
it "routes to #create" do
expect(post: "/posts").to route_to("posts#create")
end
end
end