I am working through "Agile Web Development with Rails 4" and I've run in to this issue in Chapter 7, Task B: Validation and Unit Testing. Any help would be appreciated.
When I try to add a new entry this is the error I get.
undefined method `titles' for #Product:0x007fa6fcbf28e0
Extracted source (around line #30):
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render action: 'show', status: :created, location: #product }
else
if #product.save is line 30.
This started after adding these lines to my products.rb in /rails/depot_a/app/models
class Product < ActiveRecord::Base
validates :titles, :description, :image_url, presence: true
validates :price, numericality: {greater_than_or_equal_to: 0.01}
validates :title, uniqueness: true
validates :image_url, allow_blank: true, format: {
with: %r{\.(gif|jpg|png)\Z}i,
message: 'must be a URL for GIF, JPG, or PNG image.'
}
end
This is my products_controller.rb in /rails/depot_a/app/controllers which was mentioned in the error.
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
# GET /products
# GET /products.json
def index
#products = Product.all
end
# GET /products/1
# GET /products/1.json
def show
end
# GET /products/new
def new
#product = Product.new
end
# GET /products/1/edit
def edit
end
# POST /products
# POST /products.json
def create
#product = Product.new(product_params)
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render action: 'show', status: :created, location: #product }
else
format.html { render action: 'new' }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
respond_to do |format|
if #product.update(product_params)
format.html { redirect_to #product, notice: 'Product was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
#product.destroy
respond_to do |format|
format.html { redirect_to products_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
#product = Product.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:title, :description, :image_url, :price)
end
end
ruby 2.0.0p353
Rails 4.0.3
Related
I have two tables, company and employee, so I would like when I register an employee, his registration was also for the company that was already logged, that is, without having to have to choose which company of that employee. How would I do this in ruby on rails? I'm using gem devise to login.
Try this in your User Controller:
#user = User.new(user_params)
#user.company_id = current_company.id
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
MODEL COMPANY:
class Company < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable,
:recoverable, :rememberable, :validatable
has_many :user
end
MODEL USER (the user is the employee):
class User < ApplicationRecord
belongs_to :company
enum kind: { pattern: 0, admin: 1 }
has_many :approved
has_many :expenses
end
COMPANY CONTROLLER:
class CompaniesController < ApplicationController
before_action :set_company, only: [:show, :edit, :update, :destroy]
def pesquisa
if params[:q] != nil
#companies = Company.where("companies.name LIKE '%"+params[:q]+"%'")
else
#companies = Company.all
end
respond_to do |format|
format.html
format.json
end
end
# GET /companies
# GET /companies.json
def index
#companies = Company.all
end
# GET /companies/1
# GET /companies/1.json
def show
end
# GET /companies/new
def new
#company = Company.new
end
# GET /companies/1/edit
def edit
end
# POST /companies
# POST /companies.json
def create
#company = Company.new(company_params)
respond_to do |format|
if #company.save
format.html { redirect_to #company, notice: 'Company was successfully created.' }
format.json { render :show, status: :created, location: #company }
else
format.html { render :new }
format.json { render json: #company.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /companies/1
# PATCH/PUT /companies/1.json
def update
respond_to do |format|
if #company.update(company_params)
format.html { redirect_to #company, notice: 'Company was successfully updated.' }
format.json { render :show, status: :ok, location: #company }
else
format.html { render :edit }
format.json { render json: #company.errors, status: :unprocessable_entity }
end
end
end
# DELETE /companies/1
# DELETE /companies/1.json
def destroy
#company.destroy
respond_to do |format|
format.html { redirect_to companies_url, notice: 'Company was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_company
#company = Company.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def company_params
params.require(:company).permit(:name, :responsible, :telefone, :email, :password, :password_confirmation)
end
end
USER CONTROLLER
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
# GET /users
# GET /users.json
def index
#users = User.all
end
# GET /users/1
# GET /users/1.json
def show
end
def pesquisa
if params[:q] != nil
#users = User.where("users.name LIKE '%"+params[:q]+"%'")
else
#users = User.all
end
respond_to do |format|
format.html
format.json
end
end
# GET /users/new
def new
#user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:name, :cpf, :kind, :timeid, :company_id)
end
end
I'm learning ROR. Trying to build this model: one user can have many store each store can have many product. I've been able to create store linking to its owner but I'm stuck at doing the same for product.
store.rb
class Store < ApplicationRecord
belongs_to :user
has_many :products, :foreign_key => :store_id
end
product.rb
class Product < ApplicationRecord
belongs_to :store
end
products_controller.rb
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
# GET /products
# GET /products.json
def index
#products = Product.all
end
# GET /products/1
# GET /products/1.json
def show
end
# GET /products/new
def new
end
# GET /products/1/edit
def edit
end
# POST /products
# POST /products.json
def create
#product = Product.new(product_params)
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: #product }
else
format.html { render :new }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
respond_to do |format|
if #product.update(product_params)
format.html { redirect_to #product, notice: 'Product was successfully updated.' }
format.json { render :show, status: :ok, location: #product }
else
format.html { render :edit }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
#product.destroy
respond_to do |format|
format.html { redirect_to products_url, notice: 'Product was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
#product = Product.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:product_name, :product_price, :product_description, :product_tag, :sku_code)
end
end
stores_controller.rb
class StoresController < ApplicationController
before_action :set_store, only: [:show, :edit, :update, :destroy]
# GET /stores
# GET /stores.json
def index
#stores = Store.all
end
# GET /stores/1
# GET /stores/1.json
def show
#products = Product.all
end
# GET /stores/new
def new
#store = Store.new
end
# GET /stores/1/edit
def edit
end
# POST /stores
# POST /stores.json
def create
#store = Store.new(store_params)
#store.user_id = current_user.id
respond_to do |format|
if #store.save
format.html { redirect_to #store, notice: 'Store was successfully created.' }
format.json { render :show, status: :created, location: #store }
else
format.html { render :new }
format.json { render json: #store.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /stores/1
# PATCH/PUT /stores/1.json
def update
respond_to do |format|
if #store.update(store_params)
format.html { redirect_to #store, notice: 'Store was successfully updated.' }
format.json { render :show, status: :ok, location: #store }
else
format.html { render :edit }
format.json { render json: #store.errors, status: :unprocessable_entity }
end
end
end
# DELETE /stores/1
# DELETE /stores/1.json
def destroy
#store.destroy
respond_to do |format|
format.html { redirect_to stores_url, notice: 'Store was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_store
#store = Store.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def store_params
params.require(:store).permit(:store_name, :store_description)
end
end
I expect when creating a product, it will get the store_id immediately. I'm keep getting "store must exist" message
From Rails 5, belongs_to requires the association object to be present. If your product object does not have a valid store_id (nil or inexistent store object), that product object will not be valid.
You can bypass this by allowing the association to be optional
class Product < ApplicationRecord
belongs_to :store, optional: true
end
Or, you should allow store_id as permitted parameter in your products_controller and pass it when you create a new product
# below code I assume that your store table has a column called 'store_name'
<%= form_for #product do |f| %>
<%= f.collection_select :store_id, current_user.stores, :id, :store_name, prompt: 'Please select the store of this product' %>
<%= f.submit %>
<% end %>
I wanted to upload image (using paperclip gem) to my product in my rails project, so i watched a youtube video how to do it (https://www.youtube.com/watch?v=Z5W-Y3aROVE) I did all he did, but i when i add a new product i get an error -
'New Product
2 errors prohibited this product from being saved:
Img url Paperclip::Errors::NotIdentifiedByImageMagickError
Img url has contents that are not what they are reported to be' , right above my new product form how do i fix it.
MY PRODUCT MODEL
class Product < ActiveRecord::Base
belongs_to :user
has_many :taggings, dependent: :destroy
has_many :tags, through: :taggings
has_attached_file :img_url, styles: { large: "800x600>", medium: "320x200>", thumb: "100x80#" }
validates_attachment_content_type :img_url, content_type: /\Aimage\/.*\z/
def self.tagged_with(name)
Tag.find_by!(name: name).products
end
def all_tags=(names)
# names="music, spotify"
self.tags = names.split(',').map do |name|
Tag.where(name: name).first_or_create!
end
end
def all_tags
tags.map(&:name).join(", ")
end
end
MY PRODUCTS_CONTROLLER
class ProductsController < ApplicationController
# before_action :authenticate_user!
before_action :set_product, only: [:show, :edit, :update, :destroy]
# GET /products
# GET /products.json
def index
if params[:tag]
#products = Product.tagged_with(params[:tag])
else
#products = Product.all
end
end
# GET /products/1
# GET /products/1.json
def show
end
# GET /products/new
def new
#product = Product.new
end
# GET /products/1/edit
def edit
end
# POST /products
# POST /products.json
def create
#product = current_user.products.new(product_params)
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: #product }
else
format.html { render :new }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
respond_to do |format|
if #product.update(product_params)
format.html { redirect_to #product, notice: 'Product was successfully updated.' }
format.json { render :show, status: :ok, location: #product }
else
format.html { render :edit }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
#product.destroy
respond_to do |format|
format.html { redirect_to products_url, notice: 'Product was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
#product = current_user.products.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:filetype, :title, :img_url, :description, :all_tags, :price, :uploaded_by, :tutorial_url)
end
end
and i displayed my images as
<%= link_to image_tag(product.img_url.url(:medium), :class =>"img-fluid tm-img"),product%>
want to increment repeated items on my shopping app
so when a users places an order and then wants to edit the order he can change the order quantities.
At the moment when i click on the quantity (i have set the quantity to 1) It goes to the order_itmes editing screen - it allows me to update the order but when i click submit get an error
NameError in OrderItemsController#update
#order_item = OrderItem.find(params[:id])
respond_to do |format|
if order_item.params[:quantity].to_i == 0 **<-----Error**
#order_item.destroy
format.html { redirect_to #order_item.order, notice: 'Item was deleted from your cart.' }
format.json { head :no_content }
parameters
{"utf8"=>"✓",
"_method"=>"patch",
"authenticity_token"=>"/8xRjbtusgdLV5SVQP55aUDccYdUzB9G23heTtEeNfk=",
"order_item"=>{"quantity"=>"2"},
"commit"=>"Update Order item",
"id"=>"68"}
order_items controller
class OrderItemsController < ApplicationController
before_action :set_order_item, only: [:show, :edit, :destroy]
before_action :load_order, only: [:create]
# GET /order_items/1/edit
def edit
end
# POST /order_items
# POST /order_items.json
def create
#order_item = #order.order_items.find_or_initialize_by_product_id(params[:product_id])
#order_item.quantity += 1
respond_to do |format|
if #order_item.save
format.html { redirect_to #order, notice: 'Successfully Added Product To Cart.' }
format.json { render action: 'show', status: :created, location: #order_item }
else
format.html { render action: 'new' }
format.json { render json: #order_item.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /order_items/1
# PATCH/PUT /order_items/1.json
def update
#order_item = OrderItem.find(params[:id])
respond_to do |format|
if order_item.params[:quantity].to_i == 0
#order_item.destroy
format.html { redirect_to #order_item.order, notice: 'Item was deleted from your cart.' }
format.json { head :no_content }
elsif #order_item.update(order_item_params)
format.html { redirect_to #order_item.order, notice: 'Successfully updated the order item.' }
else
format.html { render action: 'edit' }
format.json { render json: #order_item.errors, status: :unprocessable_entity }
end
end
end
# DELETE /order_items/1
# DELETE /order_items/1.json
def destroy
#order_item.destroy
respond_to do |format|
format.html { redirect_to #order_item.order }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_order_item
#order_item = OrderItem.find(params[:id])
end
def load_order
#order = Order.find_or_initialize_by_id(session[:order_id], status: "Unsubmitted", user_id: session[:user_id])
if #order.new_record?
#order.save!
session[:order_id] = #order.id
end
end
# Never trust parameters from the scary internet, only allow the white list through.
def order_item_params
params.require(:order_item).permit(:product_id, :order_id, :quantity)
end
end
order.controller
class OrdersController < ApplicationController
before_action :set_order, only: [:show, :edit, :update, :destroy, :confirm]
# GET /orders
# GET /orders.json
def index
#orders = Order.all
end
# GET /orders/1
# GET /orders/1.json
def show
end
# GET /orders/new
def new
#order = Order.new
end
# GET /orders/1/edit
def edit
end
# POST /orders
# POST /orders.json
def create
#order = Order.new(order_params)
respond_to do |format|
if #order.save
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render action: 'show', status: :created, location: #order }
else
format.html { render action: 'new' }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /orders/1
# PATCH/PUT /orders/1.json
def update
respond_to do |format|
if #order.update(order_params.merge(status: 'submitted'))
format.html { redirect_to confirm_order_path(#order), notice: 'Order was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# DELETE /orders/1
# DELETE /orders/1.json
def destroy
#order.destroy
respond_to do |format|
format.html { redirect_to products_path }
format.json { head :no_content }
end
end
def confirm
end
private
# Use callbacks to share common setup or constraints between actions.
def set_order
#order = Order.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def order_params
params.require(:order).permit(:user_id, :status, :address_id)
end
end
order_item.rb
class OrderItem < ActiveRecord::Base
belongs_to :order
belongs_to :product
validates :order_id, :product_id, presence: true
validates :quantity, numericality: { only_integer: true, greater_than: 0 }
def subtotal
quantity * product.price
end
end
just seen it if order_item.params[:quantity].to_i == 0
should be if order_item_params[:quantity].to_i == 0
I have 2 forms, a orders form and a products form. I would like the products form to be under the orders form. I am getting this error: Can't mass-assign protected attributes: products_attributes.
Here is my orders model
class Order < ActiveRecord::Base
attr_accessible :comments, :due_date, :order_type, :print_color, :print_location, :title,
:products
validates :order_type, :due_date, :print_color, :title, :presence => true
validates :title, :uniqueness => true
has_many :products
accepts_nested_attributes_for :products, :allow_destroy => true
end
products model
class Product < ActiveRecord::Base
attr_accessible :quantity
has_one :order
end
orders controller:
>class OrdersController < ApplicationController
# GET /orders
# GET /orders.json
def index
#orders = Order.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #orders }
end
end
# GET /orders/1
# GET /orders/1.json
def show
#order = Order.find(params[:id])
#products = #order.products.find(:all)
respond_to do |format|
format.html # show.html.erb
format.json { render json: #order }
end
end
# GET /orders/new
# GET /orders/new.json
def new
#order = Order.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #order }
end
end
# GET /orders/1/edit
def edit
#order = Order.find(params[:id])
end
# POST /orders
# POST /orders.json
def create
#order = Order.new(params[:order])
respond_to do |format|
if #order.save
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render json: #order, status: :created, location: #order }
else
format.html { render action: "new" }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# PUT /orders/1
# PUT /orders/1.json
def update
#order = Order.find(params[:id])
respond_to do |format|
if #order.update_attributes(params[:order])
format.html { redirect_to #order, notice: 'Order was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# DELETE /orders/1
# DELETE /orders/1.json
def destroy
#order = Order.find(params[:id])
#order.destroy
respond_to do |format|
format.html { redirect_to orders_url }
format.json { head :no_content }
end
end
end
any help would be appreciated! thanks in advance.
Replace:
attr_accessible ..., :products
With:
attr_accessible ..., :products_attributes