I implemented a function to stock articles like "qiita" in Rails, so I will summarize the method as a memorandum. (Basically the same way as the like function)
-Create a button to stock articles. -Display how much articles are in stock. -Allow stocked posts to be checked on the stock list page.
The first step in implementing the stock feature is to create a Stock model
.
$ rails g model Stock
Create two columns.
-Post_id
column
-User_id
column
Modify the migration file as follows.
xxxxxxxxxxxxx_create_stocks.rb
class CreateStocks < ActiveRecord::Migration[6.0]
def change
create_table :stocks do |t|
t.references :user, foreign_key: true
t.references :post, foreign_key: true
t.timestamps
end
add_index :stocks, [:user_id, :post_id], unique: true
end
end
$ rails db:migrate
Add each of the two columns as a foreign key.
This table will be used as an intermediate table to store information such as ** who stocked which post **.
Also, set the index so that the combination of the user_id
column and the post_id
column is unique.
Set up the association as follows:
Add validation to stock.rb
in addition to the association.
user.rb
user.rb
has_many :stocks, dependent: :destroy
post.rb
post.rb
has_many :stocks, dependent: :destroy
stock.rb
stock.rb
belongs_to :user
belongs_to :post
validates :user_id, presence: true
validates :post_id, presence: true
Then create a stock controller
.
$ rails g controller Stocks
stocks_controller.rb
After creating the stock controller
, define the actions required for this implementation.
stocks_controller.rb
class StocksController < ApplicationController
def create
@stock = current_user.stocks.create(post_id: params[:post_id])
redirect_back(fallback_location: root_path)
end
def destroy
@stock = Stock.find_by(
post_id: params[:post_id],
user_id: current_user.id
)
@stock.destroy
redirect_back(fallback_location: root_path)
end
def index
@stocks = Stock.where(user_id: current_user.id)
end
end
posts_controller.rb
Then add a variable to the ** show action ** part of the post controller
.
This is to display the stock button on the post/show page.
posts_controller.rb
def show
@post = Post.find_by(id: params[:id])
@stock = Stock.find_by(
user_id: current_user.id,
post_id: @post.id
)
end
Next, we will add the necessary routing. routes.rb
routes.rb
resources :stocks, only:[:create, :destroy, :index]
This time, in addition to the stocking function ** (create) ** and the stocking release function ** (destroy) **, ** "index" ** for displaying stocked articles is also added.
Define a stock?
Method so that the user can check if the article is already in stock.
user.rb
user.rb
#Check if the user is already in stock
def stock?(post)
self.stocks.exists?(post_id: post.id)
end
In order to implement the stock button, we will first create three partials. shared/_stock.html.erb
ruby:_stock.html.erb
<%= form_with(url:stocks_path, local: true) do |f| %>
<div><%= hidden_field_tag :post_id, @post.id %></div>
<%= f.submit "stock", class:"btn-sm" %>
<% end %>
shared/_unstock.html.erb
ruby:_unstock.html.erb
<%= form_with(url: stock_path(@stock), html: {method: :delete}, local: true) do |f| %>
<div><%= hidden_field_tag :post_id, @post.id %></div>
<%= f.submit "Stop stocking", class:"btn-sm" %>
<% end %>
shared/_stock_form.html.erb
ruby:_stock_form.html.erb
<% if current_user.stock?(@post) %>
<%= render "shared/unstock" %>
<% else %>
<%= render "shared/stock" %>
<% end %>
<%= @post.stocks.count %>
posts/show Add the following partial where you want to add the button.
ruby:show.html.erb
<%= render "shared/stock_form" %>
stocks/index.html.erb
Add a new indek
page to display stocked articles.
ruby:index.html.erb
<h1>Stock list</h1>
<h2>A list of portfolios you have stocked.</h2>
<% @stocks.each do |stock| %>
<%= link_to stock.post.name, post_path(stock.post) %>
<% end %>
That is all. I don't care about the design at all because it describes how to implement the function. Please add the design as you like.
I'm working on a portfolio. It is below. https://github.com/iittaa/Sharing_Portfolio