Commit 7946b109 by Hoang Phuc Do

Create action for user create and update their product

parent 4d26cae0
...@@ -17,3 +17,6 @@ ...@@ -17,3 +17,6 @@
/yarn-error.log /yarn-error.log
.byebug_history .byebug_history
# Ignore public/uploads folder
/public/uploads/*
\ No newline at end of file
...@@ -42,6 +42,8 @@ gem 'faker', '~> 1.6', '>= 1.6.3' ...@@ -42,6 +42,8 @@ gem 'faker', '~> 1.6', '>= 1.6.3'
gem 'kaminari', '~> 1.0', '>= 1.0.1' gem 'kaminari', '~> 1.0', '>= 1.0.1'
# Flexible authentication solution for Rails with Warden # Flexible authentication solution for Rails with Warden
gem 'devise', '~> 4.3' gem 'devise', '~> 4.3'
# Automatic Ruby code style checking tool. Aims to enforce the community-driven Ruby Style Guide.
gem 'rubocop', '~> 0.49.1'
# Use Capistrano for deployment # Use Capistrano for deployment
# gem 'capistrano-rails', group: :development # gem 'capistrano-rails', group: :development
......
...@@ -41,6 +41,7 @@ GEM ...@@ -41,6 +41,7 @@ GEM
addressable (2.5.1) addressable (2.5.1)
public_suffix (~> 2.0, >= 2.0.2) public_suffix (~> 2.0, >= 2.0.2)
arel (8.0.0) arel (8.0.0)
ast (2.3.0)
autoprefixer-rails (7.1.1) autoprefixer-rails (7.1.1)
execjs execjs
bcrypt (3.1.11) bcrypt (3.1.11)
...@@ -121,6 +122,10 @@ GEM ...@@ -121,6 +122,10 @@ GEM
nokogiri (1.8.0) nokogiri (1.8.0)
mini_portile2 (~> 2.2.0) mini_portile2 (~> 2.2.0)
orm_adapter (0.5.0) orm_adapter (0.5.0)
parallel (1.11.2)
parser (2.4.0.0)
ast (~> 2.2)
powerpack (0.1.1)
public_suffix (2.0.5) public_suffix (2.0.5)
puma (3.9.1) puma (3.9.1)
rack (2.0.3) rack (2.0.3)
...@@ -149,6 +154,8 @@ GEM ...@@ -149,6 +154,8 @@ GEM
method_source method_source
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0) thor (>= 0.18.1, < 2.0)
rainbow (2.2.2)
rake
rake (12.0.0) rake (12.0.0)
rb-fsevent (0.9.8) rb-fsevent (0.9.8)
rb-inotify (0.9.8) rb-inotify (0.9.8)
...@@ -156,6 +163,14 @@ GEM ...@@ -156,6 +163,14 @@ GEM
responders (2.4.0) responders (2.4.0)
actionpack (>= 4.2.0, < 5.3) actionpack (>= 4.2.0, < 5.3)
railties (>= 4.2.0, < 5.3) railties (>= 4.2.0, < 5.3)
rubocop (0.49.1)
parallel (~> 1.10)
parser (>= 2.3.3.1, < 3.0)
powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1)
ruby-progressbar (1.8.1)
ruby_dep (1.5.0) ruby_dep (1.5.0)
rubyzip (1.2.1) rubyzip (1.2.1)
sass (3.4.24) sass (3.4.24)
...@@ -191,6 +206,7 @@ GEM ...@@ -191,6 +206,7 @@ GEM
thread_safe (~> 0.1) thread_safe (~> 0.1)
uglifier (3.2.0) uglifier (3.2.0)
execjs (>= 0.3.0, < 3) execjs (>= 0.3.0, < 3)
unicode-display_width (1.2.1)
warden (1.2.7) warden (1.2.7)
rack (>= 1.0) rack (>= 1.0)
web-console (3.5.1) web-console (3.5.1)
...@@ -223,6 +239,7 @@ DEPENDENCIES ...@@ -223,6 +239,7 @@ DEPENDENCIES
mysql2 (>= 0.3.18, < 0.5) mysql2 (>= 0.3.18, < 0.5)
puma (~> 3.7) puma (~> 3.7)
rails (~> 5.1.1) rails (~> 5.1.1)
rubocop (~> 0.49.1)
sass-rails (~> 5.0) sass-rails (~> 5.0)
selenium-webdriver selenium-webdriver
spring spring
......
class ProductsController < ApplicationController class ProductsController < ApplicationController
before_action :authenticate_user!, only: [:new, :edit, :create, :update, :destroy]
before_action :correct_user, only: [:edit, :destroy]
def new
@product = current_user.products.build
end
def create
@product = current_user.products.build(product_params)
if @product.save
redirect_to root_url
else
render 'new'
end
end
def edit
@product = Product.find(params[:id])
end
def update
@product = Product.find(params[:id])
if @product.update(product_params)
redirect_to root_url
else
render 'edit'
end
end
private
def product_params
params.require(:product).permit(:title, :sku, :price, :description,
:category_id, :image_url)
end
def correct_user
product = current_user.products.find_by(id: params[:id])
redirect_to root_url if product.nil?
end
end end
\ No newline at end of file
module ProductsHelper module ProductsHelper
def get_product_thumbnail(product, thumbnail_width, thumbnail_height) def get_product_thumbnail(product, thumbnail_width, thumbnail_height)
product.image_url || # product.image_url always returns PictureUploader object
"product/placeholder_#{thumbnail_width}x#{thumbnail_height}" default_img_path = "product/placeholder_#{thumbnail_width}x#{thumbnail_height}"
product.image_url.present? ? product.image_url : default_img_path
end end
end end
\ No newline at end of file
class Product < ApplicationRecord class Product < ApplicationRecord
belongs_to :category belongs_to :category
belongs_to :user
mount_uploader :image_url, PictureUploader
validates :category_id, presence: true
end end
\ No newline at end of file
...@@ -3,4 +3,5 @@ class User < ApplicationRecord ...@@ -3,4 +3,5 @@ class User < ApplicationRecord
# :confirmable, :lockable, :timeoutable and :omniauthable # :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable :recoverable, :rememberable, :trackable, :validatable
has_many :products
end end
class PictureUploader < CarrierWave::Uploader::Base
# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
# include CarrierWave::MiniMagick
# Choose what kind of storage to use for this uploader:
storage :file
# storage :fog
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Provide a default URL as a default if there hasn't been a file uploaded:
# def default_url(*args)
# # For Rails 3.1+ asset pipeline compatibility:
# # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
#
# "/images/fallback/" + [version_name, "default.png"].compact.join('_')
# end
# Process files as they are uploaded:
# process scale: [200, 300]
#
# def scale(width, height)
# # do something
# end
# Create different versions of your uploaded files:
# version :thumb do
# process resize_to_fit: [50, 50]
# end
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
# def extension_whitelist
# %w(jpg jpeg gif png)
# end
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
# def filename
# "something.jpg" if original_filename
# end
end
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
<div class="form-group"> <div class="form-group">
<%= f.label :email %><br /> <%= f.label :email %>
<%= f.email_field :email, autofocus: true, class: "form-control" %> <%= f.email_field :email, autofocus: true, class: "form-control" %>
</div> </div>
</div> </div>
......
<%= form_for(@product) do |f| %>
<%= render 'shared/error_messages', object: @product %>
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<%= f.label :title %>
<%= f.text_field :title, class: "form-control" %>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<%= f.label :sku %>
<%= f.text_field :sku, class: "form-control", step: :any %>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<%= f.label :price %>
<%= f.number_field :price, class: "form-control" %>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<%= f.label :description %>
<%= f.text_area :description, class: "form-control", rows: 7 %>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<%= f.label :category, 'Product Category' %>
<%= f.collection_select :category_id, Category.all, :id, :title, { prompt: 'Select a category' }, class: 'form-control' %>
</div>
</div>
<div class="col-xs-12">
<div class="form-group">
<%= f.label :image_url, 'Product Image' %>
<%= f.file_field :image_url %>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="form-action clearfix mt-none">
<%= f.submit "Submit", class: "btn btn-primary" %>
</div>
</div>
</div>
</div>
<% end %>
\ No newline at end of file
<div class="container">
<div class="row">
<div class="col-md-9 col-md-push-3 create-product form-section">
<h1 class="h2 heading-primary font-weight-normal">
Edit Product #<%= @product.id %>
</h1>
<div class="featured-box featured-box-primary featured-box-flat featured-box-text-left mt-md">
<div class="box-content">
<%= render 'form' %>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
<div class="container">
<div class="row">
<div class="col-md-9 col-md-push-3 create-product form-section">
<h1 class="h2 heading-primary font-weight-normal">
New Product
</h1>
<div class="featured-box featured-box-primary featured-box-flat featured-box-text-left mt-md">
<div class="box-content">
<%= render 'form' %>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
<% if object.errors.any? %>
<div id="error_explanation" class="alert alert-danger">
<h4><%= pluralize(object.errors.count, "error") %> prohibited your data from being saved:</h4>
<ul>
<% object.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
\ No newline at end of file
...@@ -3,4 +3,5 @@ Rails.application.routes.draw do ...@@ -3,4 +3,5 @@ Rails.application.routes.draw do
root 'static_pages#index' root 'static_pages#index'
resources :categories resources :categories
devise_for :users devise_for :users
resources :products
end end
class AddUserRefToProducts < ActiveRecord::Migration[5.1]
def change
add_reference :products, :user, foreign_key: true
end
end
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
# #
# 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.define(version: 20170608032601) do ActiveRecord::Schema.define(version: 20170608073720) do
create_table "categories", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| create_table "categories", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.string "title" t.string "title"
...@@ -26,7 +26,9 @@ ActiveRecord::Schema.define(version: 20170608032601) do ...@@ -26,7 +26,9 @@ ActiveRecord::Schema.define(version: 20170608032601) do
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.string "image_url" t.string "image_url"
t.bigint "user_id"
t.index ["category_id"], name: "index_products_on_category_id" t.index ["category_id"], name: "index_products_on_category_id"
t.index ["user_id"], name: "index_products_on_user_id"
end end
create_table "users", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| create_table "users", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
...@@ -47,4 +49,5 @@ ActiveRecord::Schema.define(version: 20170608032601) do ...@@ -47,4 +49,5 @@ ActiveRecord::Schema.define(version: 20170608032601) do
end end
add_foreign_key "products", "categories" add_foreign_key "products", "categories"
add_foreign_key "products", "users"
end end
...@@ -11,7 +11,7 @@ Category.destroy_all ...@@ -11,7 +11,7 @@ Category.destroy_all
# Create Product Categories # Create Product Categories
4.times do |n| 4.times do |n|
title = "Category #{n}" title = "Category #{n + 1}"
desc = Faker::Lorem.paragraphs desc = Faker::Lorem.paragraphs
Category.create!(title: title, description: desc) Category.create!(title: title, description: desc)
end end
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment