個人開発のフリマは、個人開発やスタートアップで開発したプロダクトをフリマ感覚で売買できるサービスです。
個人開発のフリマ( https://t.co/pBm7hbuxOI )が始まります!個人開発で作ったサービスを売ったり、買ったりできるフリマサイトです。放置してるサービスなどある方、もしかしたら売れるかもしれませんよ‼️ ぜひ、登録してみてください☺️
— 個人開発のコミュニティ『開発会議』 (@devtalkjp) 2019年5月27日
以前、個人開発者の知見を集めたい!「開発会議」を作りましたを投稿させていただき、200名以上の個人開発者の方々にご登録いただき、より良いサービスづくりをしていく為にインタビューを始めました。そのお話をお伺いする中で、自分のサービスで食べていく以外に「サービスの売却」という選択肢を視野に入れていることが分かりました。
また、私自身も以前、開発してバズったサービスを売却しようと考えた時がありました。しかし、従来のWebメディア売買を主要取引としたサイト群では審査に落ちてしまい、結果的に商機を逃してしまったのかなと思っています。
何ができるの
ズバリ、売ったり買ったりです。
開発環境
- Rails
- Heroku
- CloudFlare
- Amazon s3
- Amazon SES
売買スキームの実装
今回の売買では決済は実装していません。いずれ実装するかもしれませんが、まずは銀行口座によるマニュアルの振込も想定しています。交渉の申し込みから、契約内容の締結までを説明していきたいと思います。
交渉に関連するモデル
class User < ApplicationRecord
has_many :businesses, dependent: :destroy
has_many :buy_negotiations, class_name: "Negotiation",
foreign_key: "buyer_id",
dependent: :destroy
has_many :sell_negotiations, class_name: "Negotiation",
foreign_key: "seller_id",
dependent: :destroy
has_many :buy_content, through: :buy_negotiations, source: :buyer
has_many :sell_content, through: :sell_negotiations, source: :seller
has_many :messages
end
class Business < ApplicationRecord
belongs_to :user
has_many :negotiations
end
class Negotiation < ApplicationRecord
before_create :set_slug
belongs_to :business
has_many :messages
belongs_to :buyer, class_name: "User"
belongs_to :seller, class_name: "User"
validates :buyer_id, presence: true
validates :seller_id, presence: true
def to_param
slug
end
private
def set_slug
loop do
self.slug = SecureRandom.uuid
break unless Negotiation.where(slug: slug).exists?
end
end
end
class Message < ApplicationRecord
belongs_to :user
belongs_to :negotiation
end
交渉(negotiation)は、URLを念の為スラッグで作るようにしています。
1) 交渉の申し込み
<%= form_with model: @negotiation, url: negotiations_path, local: true do |f| %>
<%= f.hidden_field :business_id, value: @business.id %>
<%= f.hidden_field :seller_id, value: @business.user.id %>
<%= f.hidden_field :buyer_id, value: current_user.id %>
<%= f.submit "売却の交渉を始める", class: "btn btnPrimary btnStyle" %>
<% end %>
def show
・・・
@negotiation = @business.negotiations.build
end
Businessに紐づいた、交渉(negotiation)を作っていきます。
def create
@negotiation = Negotiation.create(create_params)
if @negotiation.save
NegotiationMailer.send_notification_to_seller(@negotiation).deliver
flash[:success] = "交渉が始まりました!"
redirect_to @negotiation
else
flash[:alert] = "交渉の開始に失敗しました。"
redirect_to root_path
end
end
交渉が始まったら、売り手側にメールが飛ぶように設定しています。
2) 交渉
・・・
<div class="chatBox">
<%= render partial: 'messages/form', locals: { message: @message, negotiation: @negotiation, negotiation_id: @negotiation.id } %>
</div>
<div id="comments_area">
<%= render partial: 'messages/index', locals: { messages: @messages } %>
</div>
・・・
<%= form_with(model: [negotiation, message] ) do |form| %>
<div class="chatInput">
<%= form.text_area :content, rows: "3" %>
</div>
<div class="chatHead">
<%= form.submit "送信する" %>
</div>
<% end %>
<ul>
<% messages.each do |message| %>
<% unless message.id.nil? %>
<li>
<div class="msg">
<div class="flexContainer">
<div class="icon">
<%= image_tag message.user.image.to_s %>
</div>
<div class="text">
<div class="name">
<span><%= message.user.username %></span>
</div>
<div class="content">
<p><%= message.content %></p>
</div>
</div>
</div>
</div>
</li>
<% end %>
<% end %>
</ul>
$("#comments_area").html("<%= j(render 'index', { messages: @message.negotiation.messages }) %>")
$("textarea").val('')
メッセージのやり取りはリアルタイム性を意識して、Firebaseなどの導入も考えたのですが、最初は実用最低限でいいかなと思って、普通のJSでやりました。
def show
@negotiation = Negotiation.find_by_slug(params[:slug])
@message = Message.new
@messages = @negotiation.messages
end
def create
@message = @negotiation.messages.build(create_params)
@message.user_id = current_user.id
if @message.save
MessageMailer.send_notification_to_receiver(@message).deliver
render :index
end
end
negotiation
の綴りを何回かタイポして、エラーが起こりました。
モデル名はもっと、なるべくシンプルな方がいいですね。
サービスの使い方はCrieitさんに投稿したのでこちらを参考にしてください。
いずれ、誰かが作るサービスだなと思っていましたが、であれば気づいた自分がまずトライすべきだなと思って、見切りでリリースしていました。すぐに売れることはなくても、とりあえず登録しておけば、忘れた頃に売れるかもしれません!
まずは、自分が作ったサービスに「値付け」から始めてみませんか?