diff --git a/app/assets/javascripts/line_items.coffee b/app/assets/javascripts/line_items.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/app/assets/javascripts/line_items.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/stylesheets/line_items.scss b/app/assets/stylesheets/line_items.scss new file mode 100644 index 0000000..d7c9df4 --- /dev/null +++ b/app/assets/stylesheets/line_items.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the LineItems controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/line_items_controller.rb b/app/controllers/line_items_controller.rb new file mode 100644 index 0000000..1341422 --- /dev/null +++ b/app/controllers/line_items_controller.rb @@ -0,0 +1,74 @@ +class LineItemsController < ApplicationController + before_action :set_line_item, only: [:show, :edit, :update, :destroy] + + # GET /line_items + # GET /line_items.json + def index + @line_items = LineItem.all + end + + # GET /line_items/1 + # GET /line_items/1.json + def show + end + + # GET /line_items/new + def new + @line_item = LineItem.new + end + + # GET /line_items/1/edit + def edit + end + + # POST /line_items + # POST /line_items.json + def create + @line_item = LineItem.new(line_item_params) + + respond_to do |format| + if @line_item.save + format.html { redirect_to @line_item, notice: 'Line item was successfully created.' } + format.json { render :show, status: :created, location: @line_item } + else + format.html { render :new } + format.json { render json: @line_item.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /line_items/1 + # PATCH/PUT /line_items/1.json + def update + respond_to do |format| + if @line_item.update(line_item_params) + format.html { redirect_to @line_item, notice: 'Line item was successfully updated.' } + format.json { render :show, status: :ok, location: @line_item } + else + format.html { render :edit } + format.json { render json: @line_item.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /line_items/1 + # DELETE /line_items/1.json + def destroy + @line_item.destroy + respond_to do |format| + format.html { redirect_to line_items_url, notice: 'Line item was successfully destroyed.' } + format.json { head :no_content } + end + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_line_item + @line_item = LineItem.find(params[:id]) + end + + # Never trust parameters from the scary internet, only allow the white list through. + def line_item_params + params.require(:line_item).permit(:product_id, :cart_id) + end +end diff --git a/app/helpers/line_items_helper.rb b/app/helpers/line_items_helper.rb new file mode 100644 index 0000000..8f607da --- /dev/null +++ b/app/helpers/line_items_helper.rb @@ -0,0 +1,2 @@ +module LineItemsHelper +end diff --git a/app/models/cart.rb b/app/models/cart.rb index f3c5441..6ecba63 100644 --- a/app/models/cart.rb +++ b/app/models/cart.rb @@ -1,2 +1,3 @@ class Cart < ApplicationRecord + has_many :line_items, dependent: :destroy end diff --git a/app/models/line_item.rb b/app/models/line_item.rb new file mode 100644 index 0000000..4642391 --- /dev/null +++ b/app/models/line_item.rb @@ -0,0 +1,4 @@ +class LineItem < ApplicationRecord + belongs_to :product + belongs_to :cart +end diff --git a/app/models/product.rb b/app/models/product.rb index e8b913e..94e597e 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,4 +1,8 @@ class Product < ApplicationRecord + has_many :line_items + + before_destroy :ensure_not_referenced_by_any_line_item + validates :title, :description, :image_url, :price, presence: true validates :price, numericality: {greater_than_or_equal_to: 0.01} validates :title, uniqueness: true, length: { minimum: 5, maximum: 30 } @@ -6,4 +10,12 @@ class Product < ApplicationRecord with: %r{\.(gif|jpg|png)\Z}i, message: 'must be URL for GIF, JPG or PNG image.' } + + private + def ensure_not_referenced_by_any_line_item + unless line_items.empty? + errors.add(:base, 'Line Items present') + throw :abort + end + end end diff --git a/app/views/line_items/_form.html.erb b/app/views/line_items/_form.html.erb new file mode 100644 index 0000000..20477c8 --- /dev/null +++ b/app/views/line_items/_form.html.erb @@ -0,0 +1,27 @@ +<%= form_for(line_item) do |f| %> + <% if line_item.errors.any? %> +
+

<%= pluralize(line_item.errors.count, "error") %> prohibited this line_item from being saved:

+ + +
+ <% end %> + +
+ <%= f.label :product_id %> + <%= f.text_field :product_id %> +
+ +
+ <%= f.label :cart_id %> + <%= f.text_field :cart_id %> +
+ +
+ <%= f.submit %> +
+<% end %> diff --git a/app/views/line_items/_line_item.json.jbuilder b/app/views/line_items/_line_item.json.jbuilder new file mode 100644 index 0000000..aa77b88 --- /dev/null +++ b/app/views/line_items/_line_item.json.jbuilder @@ -0,0 +1,2 @@ +json.extract! line_item, :id, :product_id, :cart_id, :created_at, :updated_at +json.url line_item_url(line_item, format: :json) \ No newline at end of file diff --git a/app/views/line_items/edit.html.erb b/app/views/line_items/edit.html.erb new file mode 100644 index 0000000..2737da3 --- /dev/null +++ b/app/views/line_items/edit.html.erb @@ -0,0 +1,6 @@ +

Editing Line Item

+ +<%= render 'form', line_item: @line_item %> + +<%= link_to 'Show', @line_item %> | +<%= link_to 'Back', line_items_path %> diff --git a/app/views/line_items/index.html.erb b/app/views/line_items/index.html.erb new file mode 100644 index 0000000..7af7c79 --- /dev/null +++ b/app/views/line_items/index.html.erb @@ -0,0 +1,29 @@ +

<%= notice %>

+ +

Line Items

+ + + + + + + + + + + + <% @line_items.each do |line_item| %> + + + + + + + + <% end %> + +
ProductCart
<%= line_item.product %><%= line_item.cart %><%= link_to 'Show', line_item %><%= link_to 'Edit', edit_line_item_path(line_item) %><%= link_to 'Destroy', line_item, method: :delete, data: { confirm: 'Are you sure?' } %>
+ +
+ +<%= link_to 'New Line Item', new_line_item_path %> diff --git a/app/views/line_items/index.json.jbuilder b/app/views/line_items/index.json.jbuilder new file mode 100644 index 0000000..55a3879 --- /dev/null +++ b/app/views/line_items/index.json.jbuilder @@ -0,0 +1 @@ +json.array! @line_items, partial: 'line_items/line_item', as: :line_item \ No newline at end of file diff --git a/app/views/line_items/new.html.erb b/app/views/line_items/new.html.erb new file mode 100644 index 0000000..8b4cd4d --- /dev/null +++ b/app/views/line_items/new.html.erb @@ -0,0 +1,5 @@ +

New Line Item

+ +<%= render 'form', line_item: @line_item %> + +<%= link_to 'Back', line_items_path %> diff --git a/app/views/line_items/show.html.erb b/app/views/line_items/show.html.erb new file mode 100644 index 0000000..ad54038 --- /dev/null +++ b/app/views/line_items/show.html.erb @@ -0,0 +1,14 @@ +

<%= notice %>

+ +

+ Product: + <%= @line_item.product %> +

+ +

+ Cart: + <%= @line_item.cart %> +

+ +<%= link_to 'Edit', edit_line_item_path(@line_item) %> | +<%= link_to 'Back', line_items_path %> diff --git a/app/views/line_items/show.json.jbuilder b/app/views/line_items/show.json.jbuilder new file mode 100644 index 0000000..4e17338 --- /dev/null +++ b/app/views/line_items/show.json.jbuilder @@ -0,0 +1 @@ +json.partial! "line_items/line_item", line_item: @line_item \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 51eaebf..012abe1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,5 @@ Rails.application.routes.draw do + resources :line_items resources :carts root 'store#index', as: 'store_index' diff --git a/db/migrate/20161115211138_create_line_items.rb b/db/migrate/20161115211138_create_line_items.rb new file mode 100644 index 0000000..69e2658 --- /dev/null +++ b/db/migrate/20161115211138_create_line_items.rb @@ -0,0 +1,10 @@ +class CreateLineItems < ActiveRecord::Migration[5.0] + def change + create_table :line_items do |t| + t.references :product, foreign_key: true + t.belongs_to :cart, foreign_key: true + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 27e07e1..ee07383 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,13 +10,22 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20161115210150) do +ActiveRecord::Schema.define(version: 20161115211138) do create_table "carts", force: :cascade do |t| t.datetime "created_at", null: false t.datetime "updated_at", null: false end + create_table "line_items", force: :cascade do |t| + t.integer "product_id" + t.integer "cart_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["cart_id"], name: "index_line_items_on_cart_id" + t.index ["product_id"], name: "index_line_items_on_product_id" + end + create_table "products", force: :cascade do |t| t.string "title" t.text "description" diff --git a/test/controllers/line_items_controller_test.rb b/test/controllers/line_items_controller_test.rb new file mode 100644 index 0000000..ed2f9c3 --- /dev/null +++ b/test/controllers/line_items_controller_test.rb @@ -0,0 +1,48 @@ +require 'test_helper' + +class LineItemsControllerTest < ActionDispatch::IntegrationTest + setup do + @line_item = line_items(:one) + end + + test "should get index" do + get line_items_url + assert_response :success + end + + test "should get new" do + get new_line_item_url + assert_response :success + end + + test "should create line_item" do + assert_difference('LineItem.count') do + post line_items_url, params: { line_item: { cart_id: @line_item.cart_id, product_id: @line_item.product_id } } + end + + assert_redirected_to line_item_url(LineItem.last) + end + + test "should show line_item" do + get line_item_url(@line_item) + assert_response :success + end + + test "should get edit" do + get edit_line_item_url(@line_item) + assert_response :success + end + + test "should update line_item" do + patch line_item_url(@line_item), params: { line_item: { cart_id: @line_item.cart_id, product_id: @line_item.product_id } } + assert_redirected_to line_item_url(@line_item) + end + + test "should destroy line_item" do + assert_difference('LineItem.count', -1) do + delete line_item_url(@line_item) + end + + assert_redirected_to line_items_url + end +end diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb index 6e02694..0cfccf2 100644 --- a/test/controllers/products_controller_test.rb +++ b/test/controllers/products_controller_test.rb @@ -44,6 +44,14 @@ class ProductsControllerTest < ActionDispatch::IntegrationTest assert_redirected_to product_url(@product) end + test "can't delete product in cart" do + assert_difference('Product.count', 0) do + delete product_url(products(:two)) + end + + assert_redirected_to products_url + end + test "should destroy product" do assert_difference('Product.count', -1) do delete product_url(@product) @@ -51,4 +59,7 @@ class ProductsControllerTest < ActionDispatch::IntegrationTest assert_redirected_to products_url end + + + end diff --git a/test/fixtures/line_items.yml b/test/fixtures/line_items.yml new file mode 100644 index 0000000..4db5df2 --- /dev/null +++ b/test/fixtures/line_items.yml @@ -0,0 +1,10 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html +# TODO: Warum hat das hier nicht funktioniert wenn das beides in einem eigenen Cart lag? + +one: + product: two + cart: one + +two: + product: two + cart: two diff --git a/test/models/line_item_test.rb b/test/models/line_item_test.rb new file mode 100644 index 0000000..9371a40 --- /dev/null +++ b/test/models/line_item_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class LineItemTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end