I am trying to send a notification email to the email provided by the user when he clicks the place order button but i get this error
TypeError: no implicit conversion of Symbol into Integer
and the error is in order_controller.rb file here it is
class OrdersController < ApplicationController
def create
#order_form=OrderForm.new(user: User.new(order_params[:user]),cart: #cart)
if #order_form.save
notify_user
redirect_to root_path,notice:"Thank You for placing the order sir."
else
render "carts/checkout"
end
end
private
def notify_user
OrderMailer.order_confirmation(#order_form.order).deliver
end
def order_params
params.require(:order_form).permit(
user:[:name,:phone,:address,:city,:country,:postal_code,:email])
end
end
and this is the order_form.rb model
class OrderForm
include ActiveModel::Model
attr_accessor :user,:order
attr_writer :cart
def save
set_password_for_user
if valid?
persist
true
else
false
end
end
def has_error?
user.errors.any?
end
private
def valid?
user.valid?
end
def persist
user.save
#order=Order.create!(user:user)
build_order_items
end
def set_password_for_user
user.password="examplepassword"
end
def build_order_items
#cart.items.each do |item|
#order.order_items.create! product_id: item.product_id, quantity: item.quantity
end
end
end
and finally my order_mailer.rb mailer
class OrderMailer < ActionMailer::Base
default from: "bobbyverma946#yahoo.in"
def order_confirmation order
#order=order
mail to: order.user.email, subject: "Your order (##{order.id})"
end
end
can someone please tell me whats wrong with the code because i am really confused
Related
I have seen this error, I understand the problem or so I hope I do, the problem being my order_items are saving before an Order Id has been created. The problem of being a nube is having a clue about the problem but not idea about how to implement the solution, your patience is appreciated.
The error I am getting.
ActiveRecord::RecordNotSaved (You cannot call create unless the parent is saved):
app/models/shopping_bag.rb:22:in add_item'
app/controllers/order_items_controller.rb:10:increate'
My OrderItems controller
class OrderItemsController < ApplicationController
def index
#items = current_bag.order.items
end
def create
current_bag.add_item(
book_id: params[:book_id],
quantity: params[:quantity]
)
redirect_to bag_path
end
def destroy
current_bag.remove_item(id: params[:id])
redirect_to bag_path
end
end
My Orders controller
class OrdersController < ApplicationController
before_action :authenticate_user!, except:[:index, :show]
def index
#order = Order.all
end
def new
#order = current_bag.order
end
def create
#order = current_bag.order
if #order.update_attributes(order_params.merge(status: 'open'))
session[:bag_token] = nil
redirect_to root_path
else
render new
end
end
private
def order_params
params.require(:order).permit(:sub_total, :status, :user_id)
end
end
My shopping bag Model
class ShoppingBag
delegate :sub_total, to: :order
def initialize(token:)
#token = token
end
def order
#order ||= Order.find_or_create_by(token: #token, status: 'bag') do | order|
order.sub_total = 0
end
end
def items_count
order.items.sum(:quantity)
end
def add_item(book_id:, quantity: 1)
book = Book.find(book_id)
order_item = order.items.find_or_create_by(
book_id: book_id
)
order_item.price = book.price
order_item.quantity = quantity
ActiveRecord::Base.transaction do
order_item.save
update_sub_total!
end
end
def remove_item(id:)
ActiveRecord::Base.transaction do
order.items.destroy(id)
update_sub_total!
end
end
private
def update_sub_total!
order.sub_total = order.items.sum('quantity * price')
order.save
end
end
Thank you, your time is appreciated.
From docs about find_or_create_by:
This method always returns a record, but if creation was attempted and failed due to validation errors it won’t be persisted, you get what create returns in such situation.
Probably this is the situation - the record was not persisted in a database, but only created in memory. Looking at your code, I think you want to use a bang-version of the method (find_or_create_by!), which will raise an error in such situation.
To use parent attributes in child when using nested_attributes you can use inverse_of. Here is the documentation which may help you understand why parents need to be created first.
UPDATED with example: This will create forums first and then posts.
class Forum < ActiveRecord::Base
has_many :posts, :inverse_of => :forum
end
class Post < ActiveRecord::Base
belongs_to :forum, :inverse_of => :posts
end
I'm trying to place an order with braintree payment gem and everything is working fine execept one little thing
i get this error while placing the order
undefined method `total_price' for nil:NilClass
in the order_transaction.rb file which is located in app/views/services/
this is the file
class OrderTransaction
attr_reader :order,:nonce
def initialize order, nonce
#order=order
#nonce=nonce
end
def execute
#result = Braintree::Transaction.sale(
amount: #order.total_price,
payment_method_nonce: #nonce)
end
def ok?
#result.success?
end
end
and this is the method in orders_controller.rb which is creating the transaction
def charge_user
transaction=OrderTransaction.new #order,params[:payment_method_nonce]
transaction.execute
transaction.ok?
end
i dont get whats happening i have the method total_price in order model which is this
class Order < ApplicationRecord
belongs_to :user
has_many :order_items
def total_price
order_items.inject(0){|sum, item| sum +item.total_price }
end
end
i have also used attr_reader to read the order and the nonce in order_transaction.rb file so why is it showing undefined method for nil class i'm really confused can someone help me out
this is the orders controller in controller folder
class OrdersController < ApplicationController
before_filter :initialize_cart
def create
#order_form=OrderForm.new(user: User.new(order_params[:user]),cart: #cart)
if #order_form.save
notify_user
if charge_user
redirect_to products_path,notice:"Thank You for placing the order sir."
end
else
render "carts/checkout",notice:"Something went wrong please try again."
end
end
def custom
#order_form=OrderForm.new(user: current_user,cart: #cart)
if #order_form.save
notify_user
if charge_user
redirect_to products_path,notice:"Thank You for placing the order sir."
end
else
render "carts/checkout",notice:"Something went wrong please try again sir."
end
end
private
def notify_user
OrderMailer.order_confirmation(#order_form.order).deliver
end
def order_params
params.require(:order_form).permit(
user:[:name,:phone,:address,:city,:country,:postal_code,:email])
end
def charge_user
transaction=OrderTransaction.new #order,params[:payment_method_nonce]
transaction.execute
transaction.ok?
end
end
users_controller.rb
class UsersController < ApplicationController
include UsersHelper
def new
#user = User.new
end
def create
if isUsernameTaken?
render 'new'
elsif isEmailTaken?
render 'new'
else
#user = User.new(user_params)
if #user.save
else
render 'new'
end
end
end
private
def user_params
params.require(:user).permit(:username,:email,:password,:password_confirmation)
end
end
users_helper.rb
module UsersHelper
def isUsernameTaken?
!(User.find_by(username: params[:username]).nil?)
end
def isEmailTaken?
!(User.find_by(email: params[:email]).nil?)
end
end
The problem is isUsernameTaken? or isEmailTaken? never gets executed and always the else part gets executed even if I give same username again. Why is this happening?
This is because params[:username] and params[:email] are always blank in your controller. They should be params[:user][:username] or user_params[:username].
Anyway, those kind of checks belongs to the model, not the controller and there already are validators to do exactly what you want:
class User < ActiveRecord::Base
validates :email, :username, uniqueness: true
end
I'm adding a csv upload feature to my site. I want to be able to add startups to categories that I've created.
I'm getting this error:
Startup_policy.rb file
class StartupPolicy < CategoryPolicy
def create?
user.present?
end
def import?
user.present?
end
end
Startup_controller.rb
class StartupsController < ApplicationController
before_action :authenticate_user!
def create
#startup = #startupable.startups.new startup_params
#startup.user = current_user
#startup.save
redirect_to #startupable, notice: "Your startup was added succesfully."
authorize #startup
end
def import
count = Startup.import params[:file]
redirect_to category_startups_path, notice: "Imported #{count} startups"
authorize #startups
end
private
def set_category
#startup = Startup.find(params[:id])
authorize #startup
end
def startup_params
params.require(:startup).permit(:company, :url)
end
end
Startup.rb
class Startup < ActiveRecord::Base
belongs_to :startupable, polymorphic: true
belongs_to :user
def self.import(file)
counter = 0
CSV.foreach(file.path, headers: true, header_converters: :symbol) do |row|
startup = Startup.assign_from_row(row)
if startup.save
counter += 1
else
puts "#{startup.company} - #{startup.errors.full_messages.join(",")}"
end
end
counter
end
def self.assign_from_row(row)
startup = Startup.where(company: row[:company]).first_or_initialize
startup.assign_attributes row.to_hash.slice(:url)
startup
end
end
EDIT: added Category_policy.rb
class CategoryPolicy < ApplicationPolicy
def index?
true
end
def create?
user.present?
end
def update?
return true if user.present? && (user.admin? || category.user)
end
def show?
true
end
def destroy?
user.present? && user.admin?
end
private
def category
record
end
end
What am I missing here? Pundit is pretty easy to use but for some reason I'm stumped on this one.
I don't see that you've set #startups anywhere. So it's nil, which explains the error message. I assume you meant to set it to the resulting list you get after importing the CSV. Or, since all you are checking in the policy is whether you have a user, you could just authorize :startup which will get you to the right policy, and not care which startups you have.
I have a controller that handles PayPal's IPN callback. I want to mark an attendee as 'paid' and send them a confirmation email if they've successfully paid.
The mark paid action is working but the email is not sending.
Here's my controller:
class PaymentNotificationsController < ApplicationController
protect_from_forgery :except => [:create]
def create
PaymentNotification.create!(:params => params, :attendee_id => params[:invoice], :status => params[:payment_status], :transaction_id => params[:txn_id])
if params[:payment_status] == 'Complete'
#attendee = Attendee.find(params[:invoice])
## Working
#attendee.update_attribute(:paid, Time.now)
## Not Working
UserMailer.welcome_email(#attendee).deliver
end
render nothing: true
end
end
Here's my user_mailer file:
class UserMailer < ActionMailer::Base
default from: 'example#email.com'
def welcome_email(user)
#user = user
email_with_name = "#{#user.first_name} #{#user.last_name} <#{#user.email}>"
#url = 'http://example.com'
mail(
to: email_with_name,
subject: 'Welcome to Yadda Yadda'
)
end
end
Here's the weird thing, in another controller that doesn't have PayPal the mailer works:
class VendorsController < ApplicationController
def create
#vendor = Vendor.new(vendor_params)
if #vendor.save
UserMailer.welcome_email(#vendor).deliver
redirect_to vendor_success_path
else
render 'new'
end
end
end
I am pulling your answer out of your question and posting it here for future reference.
This takes two actions (mark paid and send mail). It has been moved to the model as an after_create method.
Here's the model:
class PaymentNotification < ActiveRecord::Base
...
after_create :mark_attendee_paid
private
def mark_attendee_paid
if status == 'Completed'
attendee.update_attribute(:paid, Time.now)
UserMailer.welcome_email(attendee).deliver
end
end
end