I know this is something you can't do inside of rails or aren't supposed to do but I need to somehow get the amount a user is inputing in a field of the form and use that value.
This is what my model looks like
class Deposit < ActiveRecord::Base
belongs_to :credit_card
belongs_to :user
validates :credit_card, presence: true
validates :user, presence: true
validates :tx_type, inclusion: %w(debit credit)
# validates :amount, presence: true, numericality: true
before_create :add_transaction_to_merchant
after_create :update_user_balance
attr_readonly :credit_card_id, :user_id, :fee_id, :tx_type, :status, :merchant_tx_id
attr_accessible :tx_type, :amount, :status, :merchant_tx_id, :credit_card_id,
:user_id, :user
def amount
return attributes[:amount] if attributes[:amount]
set_amount
end
def tx_type
attributes[:tx_type] || 'debit'
end
def send_receipt
Resque.enqueue(PaymentCompletedSender, self.id)
end
def update_user_balance
user_balance =user.balance + set_amount
user.balance = user_balance
user.save
end
private
def add_transaction_to_merchant
set_amount
return false if credit_card.nil?
return true unless amount > 0
result = Braintree::Transaction.sale(
amount: amount,
payment_method_token: credit_card.token,
options: { submit_for_settlement: true }
)
if result.success?
self.merchant_tx_id = result.transaction.id
# status will be authorized or submitted_for_settlement
self.status = result.transaction.status
else
errors.add(:base, result.message)
if result.transaction.nil?
# validation errors prevented transaction from being created
logger.error(result.errors)
else
self.merchant_tx_id = result.transaction.id
# status will be processor_declined, gateway_rejected, or failed
self.status = result.transaction.status
end
end
end
def set_amount
attributes[:amount]
end
end
The Controller:
# POST /deposits
# POST /deposits.json
def create
#deposit = Deposit.new(params[:deposit])
#deposit.user = current_user
#deposit.credit_card = current_user.credit_cards.try(:first)
binding.pry
respond_to do |format|
if #deposit.save
format.html { redirect_to "/", notice: 'Deposit was successfully created.' }
format.json { render json: #deposit, status: :created, location: #deposit }
else
format.html { render action: "new" }
format.json { render json: #deposit.errors, status: :unprocessable_entity }
end
end
end
This is what is params the form is sending
{"utf8"=>"✓",
"authenticity_token"=>"r0M0sRr7QO9kl0IWrJSgvj45DFrC6mbbuA+ttgEaUI0=",
"deposit"=>{"amount"=>"100"},
"commit"=>"Pay Now"}
Any thoughts on how to return the value of amount from the form in the model?
you are doing this right? #deposit = Deposit.new(params[:deposit]) if you remove the amount and set_amount method in the model, you should be able to just use amount or self.amount in the model so the following should be enough
def add_transaction_to_merchant
return false if credit_card.nil?
return true unless amount > 0
result = Braintree::Transaction.sale(
amount: amount,
payment_method_token: credit_card.token,
options: { submit_for_settlement: true }
)
Related
[enter image description here][1]
I keep getting this error message and can not figure out why it is. I believe it is because #resturant is nil. But I do not understand why it is nil.
Is there anyway to 'print or console log' the response so I can see what the problem is
[1]: https://i.stack.imgur.com/sHUrz.png
Here is the model
class Resturant < ApplicationRecord
mount_uploader :image, ImageUploader
serialize :image, JSON # If you use SQLite, add this line
belongs_to :user, optional: true
validates :name, :description, :location, :resturant, :glutenfree, :vegan, presence: true
validates :description, length: {maximum: 1000, too_long: "%{count} characters is the maximum allowed"}
validates :title, length: {maximum: 140, too_long: "%{count} characters is the maximum allowed"}
end
here is the controller:
class Resturant < ApplicationRecord
mount_uploader :image, ImageUploader
serialize :image, JSON # If you use SQLite, add this line
belongs_to :user, optional: true
validates :name, :description, :location, :resturant, :glutenfree, :vegan, presence: true
validates :description, length: {maximum: 1000, too_long: "%{count} characters is the maximum allowed"}
validates :title, length: {maximum: 140, too_long: "%{count} characters is the maximum allowed"}
end
# GET /resturants/new
def new
#resturant = Resturant.new
end
# GET /resturants/1/edit
def edit
end
# POST /resturants or /resturants.json
def create
#resturants = Resturant.new(resturant_params)
respond_to do |format|
if #resturant.save
format.html { redirect_to resturant_url(#resturant), notice: "Resturant was successfully created." }
format.json { render :show, status: :created, location: #resturant }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #resturant.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /resturants/1 or /resturants/1.json
def update
respond_to do |format|
if #resturant.update(resturant_params)
format.html { redirect_to resturant_url(#resturant), notice: "Resturant was successfully updated." }
format.json { render :show, status: :ok, location: #resturant }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #resturant.errors, status: :unprocessable_entity }
end
end
end
# DELETE /resturants/1 or /resturants/1.json
def destroy
#resturant.destroy
respond_to do |format|
format.html { redirect_to resturants_url, notice: "Resturant was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_resturant
#resturant = Resturant.find(params[:id])
end
# Only allow a list of trusted parameters through.
def resturant_params
params.require(:resturant).permit(:name, :genre, :description, :location, :glutenfree, :vegan, :image, :resturant)
end
end
You have a typo. (It often takes a second set of fresh eyes to see these.)
You have accidentally pluralized resturant in your create action but then are using the singular later on.
You have:
#resturants = Resturant.new(resturant_params)
Change it to:
#resturant = Resturant.new(resturant_params)
(You are also misspelling "Restaurant" throughout your entire application. It is up to you if you'd like to fix that or not. I know I myself have trouble spelling that one for some silly reason.)
I am trying to set the gender validation depending on the penultimate digit of the PESEL number (if the digit is even, then the gender is 'female'). For now my Profile.rb look like that:
class Profile < ApplicationRecord
enum gender: %i[male female]
validates :first_name, presence: true, on: :update
validates :last_name, presence: true, on: :update
validates :gender, presence: true, on: :update
validates :pesel, presence: true, on: :update
validates :contact_number, presence: true, on: :update
validates :pesel, format: { with: /\A(\d{11})\z/ }, on: :update
validate :gender_correct?
def gender_correct?
return self.pesel.blank?
if self.pesel[-2].to_i % 2 != 0
pesel_gender = 'male'
else
pesel_gender = 'female'
end
if pesel_gender != self.gender
errors.add(:gender, t('activerecord.errors.models.profile.attributes.gender.wrong'))
end
end
Unfortunately it doesn't work. Other validations works fine.
EDIT:
My update action:
def update
#profile = Profile.find(params[:id])
respond_to do |format|
#profile.avatar.attach(params[:avatar]) if params[:avatar].present?
if #profile.errors.empty? && #profile.update(profile_params)
#profile.onboarded = true
#profile.save
#profile.fill_info!
#profile.assign_dispensary
format.html { redirect_to authenticated_root_path, notice: t('.update.success') }
format.json { render :show, status: :ok, location: #profile }
else
format.html { render 'pages/info', alert: t('.update.error') }
format.json { render json: #profile.errors, status: :unprocessable_entity }
end
end
end
If i tried to update profile with blank first/last name, pesel, gender or contact number,then an error is displayed below text field.
Before update:
https://drive.google.com/file/d/1uS30WKLBFt5jcUUycI4CQblnEOpkrWEc/view?usp=sharing
After update:
https://drive.google.com/file/d/1HJqk-0opJdoZQ37CkPwscfL8Ohb19n6A/view?usp=sharing
I wanted to display error "PESEL does not match the set gender. Correct the PESEL number." under gender text field if PESEL gender doesn't match selected gender. Is that enough info? Or should I add something else?
I'm getting the following error when trying access the log in method of my sessions controller:
JWT::DecodeError (Nil JSON web token):
lib/json_web_token.rb:11:in `decode'
app/helpers/sessions_helper.rb:15:in `current_user'
app/controllers/api/sessions_controller.rb:11:in `create'
If I comment out my render json: user in my controller response, all is good, except I need to respond with the user...Why on earth is the current_user method called on through line 11 of the sessions_controller.rb. Here's the relevant code:
lib/json_web_token.rb
require 'jwt'
class JsonWebToken
def self.encode(payload, expiration = 24.hours.from_now)
payload = payload.dup
payload['exp'] = expiration.to_i
JWT.encode(payload, Rails.application.secrets.json_web_token_secret)
end
def self.decode(token)
JWT.decode(token, Rails.application.secrets.json_web_token_secret).first
end
end
sessions_helper.rb
require 'json_web_token'
module SessionsHelper
def create_session(user)
session[:user_id] = user.id
end
def current_user
auth_token = request.headers["Authorization"]
if auth_token
auth_token = auth_token.split(" ").last
begin
decoded_token = JsonWebToken.decode auth_token
rescue JWT::ExpiredSignature
return
end
#current_user ||= User.find_by(auth_token: auth_token)
end
end
def log_out(user)
logged_in? ? user.generate_authentication_token! : user.destroy_token!
auth_token = user.auth_token
user.update_attribute(:auth_token, auth_token)
end
def logged_in?
current_user.present?
end
def authenticate_with_token!
render json: { errors: "Not authenticated" }, status: :unauthorized unless logged_in?
end
def log_in(user)
create_session(user)
user.generate_authentication_token!
user.update_attribute(:auth_token, user.auth_token)
end
def authenticate_as_self_or_admin!
render json: { errors: "Not authorized" }, status: :unauthorized unless is_self? || is_admin?
end
def is_self?
user = User.find(params[:id])
auth_token = request.headers["Authorization"]
auth_token = auth_token.split(" ").last if auth_token
user.auth_token != auth_token
end
def is_admin?
if logged_in? && current_user.authenticate(params[:password])
current_user.admin
end
end
end
sessions_controller.rb
class Api::SessionsController < ApplicationController
before_action :authenticate_with_token!, only: [:destroy]
def new
end
def create
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
log_in user
render json: user, status: :created
else
render json: user, status: :unprocessable_entity
end
end
def destroy
log_out current_user
render status: 204
end
end
user.rb
require 'json_web_token'
class User < ApplicationRecord
attr_reader :current_password
before_save { email.downcase! }
before_create :generate_authentication_token!
before_update :reset_confirmed!, :if => :email_changed?
has_secure_password
has_many :posts
has_many :comments
has_many :votes
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 }, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }
validates :username, presence: true, length: { maximum: 24 }, uniqueness: { case_sensitive: false }
validates :password, presence: true, length: { minimum: 8 }
validates :auth_token, uniqueness: true
def generate_authentication_token!
begin
self.auth_token = JsonWebToken.encode('id' => self.id, 'username' => self.username, 'email' => self.email, 'bio' => self.bio, 'confirmed' => self.confirmed, 'admin' => self.admin, 'points' => self.points)
end while self.class.exists?(auth_token: auth_token)
end
def destroy_token!
self.auth_token = nil
end
def reset_confirmed!
self.confirmed = false
end
def upvotes
self.votes.where(polarity: 1)
end
def downvotes
self.votes.where(polarity: -1)
end
def update_with_password(user_params)
current_password = user_params.delete(:current_password)
user_params[:password] = current_password if user_params[:password].nil?
if self.authenticate(current_password)
self.update(user_params)
else
self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
false
end
end
end
No, I am not using devise.
I'm really hoping my eyes are just tired here...
It turns out that current_user was in fact being called since it is the default scope_name for Active Model Serializers. I changed the name of my current_user method to avoid this conflict. Here are the relevant docs.
am new to rails, I have a rails app that allows me to create a deadline by providing a title, date and description and it creates a countdown, the problem is I want to sort all the deadlines by the date entered, how do i do that in my index method?
class DeadlinesController < ApplicationController
def new
#deadline = current_user.deadlines.new
end
def create
#deadline = current_user.deadlines.new(params[:deadline].permit(:title, :date, :description))
if #deadline.save
redirect_to #deadline
else
render 'new'
end
end
def show
#deadline = Deadline.find(params[:id])
end
def edit
#deadline = current_user.deadlines.find(params[:id])
end
def index
#deadlines = current_user.deadlines.all
#deadlines = current_user.deadlines.paginate(:page => params[:page], :per_page => 5)
end
def update
#deadline = current_user.deadlines.find(params[:id])
if #deadline.update(params[:deadline].permit(:title, :date, :description))
redirect_to #deadline
else
render 'edit'
end
end
def destroy
#deadline = current_user.deadlines.find(params[:id])
#deadline.destroy
redirect_to deadlines_path
end
private
def post_params
params.require(:deadline).permit(:title, :date, :description)
end
end
deadlines model:
class Deadline < ActiveRecord::Base
validates :title, presence: true,
length: { minimum: 8 }
validates :date, presence: true
validates :description, presence: true,
length: { maximum: 230 }
#validates_format_of :date, :with => /\A[0-9]{4}-[0-1][0-9]-[0-3][0-9]\z/, :message => "Enter Date in this format: YYYY-MM-DD"
belongs_to :user
end
#deadlines = current_user.deadlines.order(:date)
.paginate(:page => params[:page], :per_page => 5)
You can use the order method
#deadlines = current_user.deadlines.order(:date)
You can also specify ascending or descending using,
#deadlines = current_user.deadlines.order(date: :asc) # Ascending
#deadlines = current_user.deadlines.order(date: :desc) # Descending
Morning All,
After spending most of the night figuring out how to put a limit on my model creation I finally got somewhere. The nested statement is now presenting me with not saved which is great news.
However I cannot seem to get the redirect or flash[:base] to work. Here is the code below:
class SnippetsController < ApplicationController
before_filter :find_book
def create
if #snippet = #book.snippets.create!(params[:snippet])
redirect_to #book
else
flash[:base]
#render
end
end
def approve
##snippet = #book.snippet.find(params[:id])
if #snippet.update_attribute(:approved, true)
redirect_to users_path
else
render root_path
end
end
def edit
#snippet = #book.snippets.find(params[:id])
end
def update
#snippet = #book.snippets.find(params[:id])
respond_to do |format|
if #snippet.update_attributes(params[:snippet])
format.html { redirect_to #book, notice: 'Comment was successfully updated.' }
else
format.html { render action: "edit" }
end
end
end
private
def find_book
#book = Book.find(params[:book_id])
end
end
Models parent (book)
class Book < ActiveRecord::Base
has_many :snippets
attr_accessible :title, :book_id, :size
def snippets_limit_reached?
if size == 0
self.snippets.count >= 2
elsif size == 1
self.snippets.count >= 3
elsif size == 2
self.snippets.count >= 4
else
return false
end
end
end
Child (Snippet)
class Snippet < ActiveRecord::Base
before_create :check_limit
belongs_to :book
attr_accessible :content, :book_id
validates :book_id, presence: true
def check_limit
if book.snippets_limit_reached?
errors.add :base, 'Snippet limit reached.'
return false
end
return true
end
end
Let me know if you need anything else, just fyi when it's running I cannot get past the nested create!
if #snippet = #book.snippets.create!(params[:snippet])
Bang methods (create!, save!) throw errors when unsuccessful, instead of returning, what evaluates to false.
Removing the bang should fix this problem.