I'm using a custom validator via rails, but my validator always creates the record but than fails the save check. Why ?
customers_controller.rb
#coupon = Coupon.create(user_unique_identifier: params[:UDID], promo_code: params[:code])
unless !#coupon.save
##always fails here
coupon.rb
validate :one_per_customer, :before => :create
private
def one_per_customer
if self.is_paid_session
return true
else
#coupon = Coupon.where(user_unique_identifier: self.user_unique_identifier, promo_code: self.promo_code).first
if #coupon.present?
errors.add(:user_unique_identifier, 'PROMO CODE ALREADY APPLIED TO THIS DEVICE')
return false
else
return true
end
end
end
Related
I've got a field from github webhook - webhook.repository.private - which checks if created repository was private (boolean). I want use return if block to handle scenario:
check if webhook.repository.private is true and if not call new class PublicRepositoryCreated but if this is true - return and execute fields_hash
code below:
def required_fields
PublicRepositoryCreated.new(webhook).call unless webhook.repository.private
fields_hash
end
private
def fields_hash
{
'fields' => {
'summary' => 'summary',
'description' => 'description',
'project' => '123'
}
}
end
Right now it seems that fields_hash is still executed even when webhook.repository.private is false
You have multiple ways of solving your problem.
You can either :
call your function and return
def required_fields
PublicRepositoryCreated.new(webhook).call && return unless webhook.repository.private
fields_hash
end
return your function
def required_fields
return PublicRepositoryCreated.new(webhook).call unless webhook.repository.private
fields_hash
end
use a ternary
def required_fields
webhook.repository.private ? fields_hash : PublicRepositoryCreated.new(webhook).call
end
I have a Sidekiq worker and in it using a case statement:
module Api
def self.authenticate(company_id)
Thread.current['api_company_id'] = company_id
yield if block_given?
ensure
Thread.current['api_company_id'] = nil
end
end
module Apis
class PollTrackableJobWorker
include Sidekiq::Worker
class EDocumentNotDoneError < StandardError; end
class UnhandledCaseError < StandardError; end
def perform(job_id, _invoice_id)
Api.authenticate(1) do
response = Api::TrackableJob.find(job_id).first
case response['status']
when 'done' then return true
when 'error' then return handle_error(response['errors'])
when 'pending' || 'running' then return raise EDocumentNotDoneError
else raise UnhandledCaseError, response
end
end
end
private
def handle_error(exception)
Bugsnag.notify(exception) if defined?(Bugsnag)
end
end
end
#perform method is tested for all possible outcomes. Below, is a case for done:
class PollTrackableJobWorkerTest < ActiveSupport::TestCase
test 'status is done' do
response = {
'type' => 'trackable_jobs',
'id' => 'xxxxx',
'status' => 'done',
'errors' => nil
}
Api.expects(:authenticate).with(1).yields
Api::TrackableJob.stubs(:find).with('xxxxx').returns([response])
assert_equal(true, Apis::PollTrackableJobWorker.new.perform('xxxxx', 123))
end
end
The test passes perfectly.
However, when I use implicit return, it keeps failing (returns nil).
For example, using a private method with an explicit return statement fails
case response['status']
when 'done' then returns_true
# code omitted
end
private
def returns_true
return true
end
or using implicit return fails too
when 'done' then true
Why do I need explicit return for case statements?
I want to create custom validation inside The Model.
But nothing in return when i tried to get that value from the variable
This is my model
validate :permanent_event_check
private
def permanent_event_check
param_activity = #activity
# puts "param_activityparam_activityparam_activity"
# puts #activity
# puts param_activity
# puts "param_activityparam_activityparam_activityparam_activity"
if param_activity.permanent == "false"
if param_activity.start_at == "" || param_activity.end_at == ""
#activity.errors[:base] << "You can't leave start and end date blank with Permanent Event"
return false
end
end
end
This is my controller
def create
#activity = admin_current_user.activities.build(activity_param)
if #activity.save
flash[:success] = "Activity Created!"
redirect_to admin_dashboard_url
else
render 'new'
end
end
private
def activity_param
params.require(:activity).permit(:name,:details,:start_at,:end_at,
:activity_image01_url,:activity_image02_url,:activity_image03_url,
:youtube_url,:capacity,:booking_status,:rules,:apply_details,
:payment_price,:payment_need,:avaliable,:rating,:temple_id)
end
But it return nil when i tried to get the value from #activity inside my model.
How can i fix this?
Thanks!
You cannot assign the object like that in the model, instead you van take self.
validates :permanent_event_check
private
def permanent_event_check
if self.permanent == "false"
if self.start_at == "" || self.end_at == ""
self.errors[:base] << "You can't leave start and end date blank with Permanent Event"
return false
end
end
end
I assume that permanent is boolean, start_at and end_at - datetime.
validate :permanent_event_check, unless :permanent
private
def permanent_event_check
# if start_at and end_at are not filled they will be nil which is interpreted as false
unless start_at && end_at
self.errors[:base] << "You can't leave start and end date blank with Permanent Event"
end
end
I have some models which share the same functionality just on other paths. So I decided to put these methods in a module and set the path in the model. My problem is that I'm not able to access the attribute in my module.
model:
class Job < ActiveRecord::Base
include ImageModel
image_dir = "jobs"
end
module:
module ImageModel
extend ActiveSupport::Concern
def delete_image
unless pic_link == "" || pic_link == nil
begin
if File.delete(Rails.root.join("public", "images", image_dir, pic_link))
return true
else
return false
end
rescue
return true #an error occured but when the image does not exist we still return true
end
end
return true
end
def replace_image(new_image)
File.open(Rails.root.join("public", "images", image_dir, new_image.original_filename), "wb") do |f|
if f.write new_image.read
delete_image
pic_link = new_image.original_filename
return true #everything went fine
else
return false #return false if new image could not be written
end
end
end
end
The error i get:
undefined local variable or method `image_dir' for #<Job:0x007f8a93b9e8d8>
on this line:
File.open(Rails.root.join("public", "images", image_dir, new_image.original_filename), "wb") do |f|
Did I miss something or did I oversee something important?
Felix
I think the design of module still have room to improve. But for this specific question, here is the quickfix.
class Job < ActiveRecord::Base
include ImageModel
def image_dir
"jobs"
end
end
You should define your image_dir = "jobs" in the module itself. because you are including your module in your model, and your module is not able to get the declaration, you have done in your model.
Or you can change your delete_image method to take parameters :
def delete_image(image_dir)
unless pic_link == "" || pic_link == nil
begin
if File.delete(Rails.root.join("public", "images", image_dir, pic_link))
return true
else
return false
end
rescue
return true #an error occured but when the image does not exist we still return true
end
end
return true
end
and where you are calling that method, pass an argument like this:
delete_image("jobs")
same in the case of replace_image method:
def replace_image(new_image, image_dir)
File.open(Rails.root.join("public", "images", image_dir, new_image.original_filename), "wb") do |f|
if f.write new_image.read
delete_image
pic_link = new_image.original_filename
return true #everything went fine
else
return false #return false if new image could not be written
end
end
end
Hope it will help. Thanks
How can I fix this error? I want to DRY my controller, and in each method I perform a sanity check on params[], just making sure all params are present.
The problem is with lambda's return. As it is defined
def validate_input(parameters)
return proc {
if parameters.find_index { |i| i.nil? }
error_message = {'Error' => 'Please fix some params'}.to_json
render :json => error_message and return
end
}
end
Then, inside my controller action I do:
def action
...
validate_input([my_sane_id, my_other_param]).call
...
end
And get the error: unexpected return.
def validate_input(*parameters)
if parameters.any?(&:nil?)
render :json => { :error => 'Please fix some params' }
false
else
true
end
end
def action
...
return unless validate_input(my_sane_id, my_other_param)
...
end
you can use the splat operator ("*") to get unknown number of parameters into array
you can use ("any?") method instead of index (which is location)
you can use symbol to proc ("&:") if you only making the function call on each item in array
you dont need to call to_json if you render json
better use symbol as hash key (":error")
you return true/false to indicate if everything ok, and if its false, just return from the action