Using 'if', '&&', and '||' in one condition statement - ruby-on-rails

So what I am trying to accomplish is if #provider.licenses.where(issuing_state:'CA')' it has to match the #form.state as well which would be 'CA' in this case in order to have access to that page. Now if the provider.licenses.issuing_state does not match #form.state the user would be redirect. Here is what I have
def edit
#user = current_user
#patient = Patient.find(params[:patient_id])
#form_response = FormResponse.find_by_id(params[:id])
#form = #form_response.form
#provider = current_user.try(:provider)
#provider_user = #provider.try(:role).try(:user)
if current_user.is_provider?
if #provider.licenses.where(issuing_state:'CO') && #form.state == 'CA' || #provider.licenses.where(issuing_state:'CA') && #form.state == 'CO'
redirect_to root_path, alert: 'You do not have access to update form'
end
end
end

Something like #provider.licenses.where(..) is always trueish because it returns a ActiveRecord::Relation.
You might want to use #provider.licenses.exist?(issuing_state:'CO') instead.
if #provider.licenses.exist?(issuing_state:'CO') && #form.state == 'CA' ||
#provider.licenses.exist?(issuing_state:'CA') && #form.state == 'CO'
redirect_to root_path, alert: 'You do not have access to update form'
end

Related

Token should not be created if a user is already signed in and already has a token

Following is the create action of DeviseTokenAuth Sessions Controller.
def create
field = (resource_params.keys.map(&:to_sym) & resource_class.authentication_keys).first
#resource = nil
if field
email_value = get_case_insensitive_field_from_resource_params(field)
#resource = find_resource(field, email_value)
end
if #resource && valid_params?(field, email_value) && #resource.active_for_authentication? #this return true
debugger
valid_password = #resource.valid_password?(resource_params[:password])
if (#resource.respond_to?(:valid_for_authentication?) && !#resource.valid_for_authentication? { valid_password }) || !valid_password
return render_create_error_bad_credentials
end
debugger
#token = #resource.create_token
#resource.save
sign_in(:user, #resource, store: false, bypass: false)
yield #resource if block_given?
render_create_success
elsif #resource && !(#resource.active_for_authentication?)
if #resource.respond_to?(:locked_at) && #resource.locked_at
render_create_error_account_locked
else
render_create_error_not_confirmed
end
else
render_create_error_bad_credentials
end
end
I am using postman, for now if a user is signed in and again tries to sign in , it goes and sign in again and create token again. I want if a user is signed in, token should not generated again and again

How to test destroy failure in ruby-on-rails

everyone.
I'm gonna test an active record object destroy failure but I've problems creating a failure situation.
I have a before_filter method called 'require_user_payment_info' which validates the #payment_info object before the delete method is called, so I can't create a 'bad' #payment_info object before the delete method is called.
Here's the require_user_payment_info method:
def require_user_payment_info
#payment_info = credit_card_model.slave.find_by_user_guid(user_guid)
if !#payment_info || #payment_info.user_guid != user_guid
redirect_to(:controller => 'store', :action => 'index') and return false
else
if((#payment_info.card_expires_year.to_i < Date.today.year) ||
((#payment_info.card_expires_month.to_i < Date.today.month) && (#payment_info.card_expires_year.to_i == Date.today.year)))
#payment_info.card_account_public = "" #clear this out so the user is forced to re-enter the credit card number
#payment_info.valid?
flash.now[:error] = t('ui_flash_errors.card_expired_error')
end
end
end
And the actual delete method:
def delete
# required to be called via a delete request
redirect_to :action => 'edit' and return if !request.delete?
if #payment_info.destroy
flash[:notice] = "Delete SUCCESSFUL"
redirect_to :action => 'new'
else
flash[:error] = "Delete failed"
redirect_to :action => 'edit'
end
Any ideas?
This is my solution:
def test_delete
payment_info = Factory.create(:payment_info, :user_guid=>#user.guid, :card_expires_month=>'04',
:card_expires_year=>(Date.today.year+2).to_s, :cardholder_city=>"test city",
:cardholder_state=>'NC', :cardholder_country=>'US', :cardholder_zip=>'27612')
PaymentInfo.any_instance.stubs(:destroy).returns(false)
delete(:delete, {}, #session)
assert_response(:redirect)
assert_equal false, assigns(:payment_info).blank?
assert_redirected_to({:controller=>'account', :action=>'edit'})
assert_equal flash[:error], "There was an error deleting your credit card information. Please try again."
end

RAILS: db count is always 0 in spec

Here is a simple case of spec in Rails 4.2:
it "returns redirect to Save & Copy" do
user_access = FactoryGirl.create(:user_access, :action => 'create', :resource =>'simple_orderx_orders', :role_definition_id => #role.id, :rank => 1,
:sql_code => "")
session[:user_id] = #u.id
q1 = FactoryGirl.create(:simple_orderx_order)
q = FactoryGirl.attributes_for(:simple_orderx_order)
FactoryGirl.create(:project_misc_definitionx_misc_definition, :resource_id => q1.id, :resource_string => 'simple_orderx_orders', definition_category: 'production_step')
expect {
get 'create', {:order => q, commit: I18n.t('Save & Copy')}
expect(response).to redirect_to URI.escape(SUBURI + "/view_handler?index=0&msg=Successfully Saved!")
}.to change(ProjectMiscDefinitionx::MiscDefinition.all.reload, :count).by(1)
end
end
In debugger, there is a new record being added to table MiscDefinition and MiscDefinition.all.count is 2, but in spec the ProjectMiscDefinitinox::MiscDefinition.all.count is always 0 and the spec case fails. What could cause the counting error in spec?
Here is the create in controller:
def create
#order = SimpleOrderx::Order.new(new_params)
#order.last_updated_by_id = session[:user_id]
#order.entered_by_id = session[:user_id]
#order.fort_token = session[:fort_token]
copy_steps(#order) if params[:commit] == I18n.t('Save & Copy') #copy mfg steps from previous order
if #order.save
copy_steps(#order.reload) if params[:commit] == I18n.t('Save & Copy') #copy mfg steps from previous order
redirect_to URI.escape(SUBURI + "/view_handler?index=0&msg=Successfully Saved!")
else
#erb_code = find_config_const('order_new_view', session[:fort_token], 'simple_orderx')
flash[:notice] = t('Data Error. Not Saved!')
render 'new'
end
end
def copy_steps(order)
obj = Order.where('drawing_num = ? AND id != ?', order.drawing_num, order.id).order('created_at DESC') if order.drawing_num.present? #find the previous order of the same drawing#
obj = Order.where('part_num = ? AND id != ?', order.part_num, order.id).order('created_at DESC') if obj.blank? && order.part_num.present?
obj = Order.where('part_name Like ? AND id != ?', "%#{order.part_name}%", order.id).order('created_at DESC') if obj.blank? && order.part_name.present?
copied = false
obj.limit(4).each do |o|
SimpleOrderx.production_step_class.where('resource_id = ? AND resource_string = ? AND definition_category = ?', o.id, params[:controller].sub('/', '_'), 'production_step').each do |r|
new_step = SimpleOrderx.production_step_class.new()
new_step = r.dup
new_step.resource_id = order.id
begin
new_step.save
copied = true
rescue => e
flash[:notice] = 'Error in copying production steps: ' + e.message
end
end
return if copied
end if obj.present?
end

Redirct_to in application controller caused infinte loop

After detect the browser page will we redirecte.
def detect_browser
redirect_to "privacy" if browser.ie6? || browser.ie7? || browser.firefox?
end
Causes the infinite loops.?
Try something like this:
def detect_browser
if(browser.ie6? || browser.ie7? || browser.firefox? ) &&
params[:controller] != "privacy", params[:action] != "show"
redirect_to "privacy"
end
end

Trying to use current_user where it is undefined

I have this call in my vote model:
fires :vote_updated, :on => :update,
:actor => :user,
:secondary_subject => :video,
:if => lambda { |vote| ((vote.value == 1) || (vote.value == -1)) && (vote.video.user != current_user)}
In case you aren't familiar, it works with the timeline_fu plugin.
I do not want the call to be fired if the user who owns the voted up video is the current user. That is where this line comes in:
:if => lambda { |vote| ((vote.value == 1) || (vote.value == -1)) && (vote.video.user != current_user)}
However, I do not have access to current_user here. How do I get around this?
Here's the create method in my votes controller (there actually is no update method):
def create
#video = Video.find(params[:video_id])
#vote = current_user.video_votes.find_or_create_by_video_id(#video.id)
if #vote.value.nil?
if params[:type] == "up"
#vote.value = 1
else
#vote.value = -1
end
elsif (params[:type] == "up" && #vote.value == 1) || (params[:type] == "down" && #vote.value == -1)
#vote.value = 0
elsif ((params[:type] == "up" && #vote.value == -1) || (params[:type] == "down" && #vote.value == 1)) || (#vote.value == 0)
if params[:type] == "up"
#vote.value = 1
else
#vote.value = -1
end
end
if #vote.save
respond_to do |format|
format.html { redirect_to #video }
format.js
end
else
respond_to do |format|
format.html
format.js
end
end
end
I believe the right thing to do would be validating this in controller. I would create a before filter for this case
UPDATE:
Just as a quick example:
before_filter :valid_vote, :only => :update
def update
#vote.update_attributes(params[:vote]) # or whatever
end
..
private
def valid_vote
#vote = Vote.find params[:id]
unless ( #vote.video.user.id != current_user.id )
render :text => 'You can't vote for your own video', :status => 403
end
end
So #vote is being declared and validated before your 'update' action is proccessed.
If it's not valid then your 'update' action stays untouched
UPDATE 2 :
not sure how you'll like it, but you could also do as follows:
in your Vote model:
attr_accessor :skip_timeline
then use the concept with before filter, but do #vote.skip_timeline = true instead of rendering text
then the statement might look as follows:
:if => lambda { |vote| ((vote.value == 1) || (vote.value == -1)) && !vote.skip_timeline }
You could also move ((vote.value == 1) || (vote.value == -1)) to your before filter :
def valid_vote
#vote = Vote.find params[:id]
unless ( [1,-1].include? #vote.value && #vote.video.user.id != current_user.id )
#vote.skip_timeline = true
end
end
and
:if => lambda { |vote| !vote.skip_timeline }
You are getting this error because it's typically not recommended to access current_user (or session information) in your model. I am not all that familiar with the timeline_fu gem, so this answer isn't going to be the greatest answer you may get. I'm merely going to show you how to access current_user from any model.
First go to your application controller. You'll want to make a method that sets the current user. You need to call the method in the before filter.
before_filter :loadCurrentUser
def loadCurrentUser
  User.currentUser = current_user
end
Then in your User model, you need to define 'currentUser'.
def self.currentUser
Thread.currentUser[:user]
end
You don't necessarily have to declare the current_user in the application controller, but since it's a gem, I'm not sure if it has an easily accessible controller.
Edit: This way may be prone to problems, but I'm not entirely sure if you were asking how to make current_user available in models, or a completely different workaround so you do not have that problem... and reading the responses of the other answer, I'm thinking it's not what you were asking.

Resources