if condition not working properly with && operator - ruby-on-rails

it also shows the link for order where received_by_admin is True.
if order.payment_status == 'Paid' && order.received_by_admin != 'true'
link_to "Payment Received", "orders/#{order.id}/?payment_status=Paid", class: "member_link", method: :put
end

probably because received_by_admin is a boolean? So
order.payment_status == 'Paid' && order.received_by_admin != true
or simpler
order.payment_status == 'Paid' && !order.received_by_admin
the point here is that true != 'true'

Related

how do I use this parameter correctly?

I have a method in my rails app.
def current_user_can_edit?(model)
user_signed_in? && (
model.user == current_user ||
(model.try(:post).present? && model.post.user == current_user)
)
end
The method is needed to check the possibility of editing the model. There are posts and events in my app. I would like to dynamically substitute a post or event for a choice, instead of a static post.
How can I write a method correctly so as not to make a lot of conditions? Like, for example, here:
def current_user_can_edit?(model, action)
if action.class.to_s == 'Post':
user_signed_in? && (
model.user == current_user ||
(model.try(:post).present? && model.post.user == current_user)
)
elsif action.class.to_s == 'Event':
user_signed_in? && (
model.user == current_user ||
(model.try(:event).present? && model.event.user == current_user)
)
end
end
In your method's logic, the expression:
model.try(:post).present? && model.post.user == current_user
can be combined by chaining two try calls:
model.try(:post).try(:user) == current_user
Now you can replace :post by a calculated value:
model.try(action.class.to_s.downcase).try(:user) == current_user
Whole code:
def current_user_can_edit?(model, action)
user_signed_in? && (
model.user == current_user ||
model.try(action.class.to_s.downcase).try(:user) == current_user
)
end
You could also use some guard clauses:
def current_user_can_edit?(model, action)
return unless user_signed_in?
return true if model.user == current_user
model.try(action.class.to_s.downcase).try(:user) == current_user
end
I'm assuming that action.class.to_s returns "Post". The code would of course be easier if you would pass :post as the method's second parameter.

Validate non model parameters are expected values in Rails

I've got a page with several URL parameters that are not model attributes that I use for sorting and filtering. Currently I'm trying to validate them in the controller like this question however am having trouble validating that a parameter is in an expected set of values.
before_filter :validate_params, :only => :index
def validate_params
if !params[:type] = 'any' || !params[:type] = 'up' || !params[:type] = 'down'
params[:type] = 'any'
end
end
In this case the value is always 'any' even if the parameter is 'up' or 'down'.
You should comapre it using == or != and not =
= is for assignment and == and != are for comparison
def validate_params
if params[:type] != 'any' || !params[:type] != 'up' || !params[:type] != 'down'
params[:type] = 'any'
end
end
OR
!['any', 'up', 'down'].include?(params[:type])
well if you think about it if params[:type] == 'up' then it is not params[:type] == 'down' so it will always set to any because you are using ||. try using && instead
if !params[:type] == 'any' && !params[:type] == 'up' && !params[:type] == 'down'
if you want to set a params[:type] that is different that any, up ordown and also use ==
The condition may look like this,
before_filter :validate_params, :only => :index
def validate_params
if params[:type] != 'any' || params[:type] != 'up' || params[:type] != 'down'
params[:type] = 'any'
end
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.

Please explain this snippet of haml code/documentation

%div{:class => [#item.type, #item == #sortcol && [:sort, #sortdir]] } Contents
could render as any of:
<div class="numeric sort ascending">Contents</div>
<div class="numeric">Contents</div>
<div class="sort descending">Contents</div>
<div>Contents</div>
I don't really understand the #sortcol && [:sort, #sortdir] part of this snippet.
This relies on operator precedence. So it is evaluated like this:
#item == #sortcol is either true or false.
when false
&& returns false because the other part is not evaluated
hence the code reduces to :class => [#item.type]
when true
&& returns the second part of the expression. In this case the array [:sort, #sortdir]
HAML automatically flattens the array before rendering thus it's equivalent to :class => [#item.type, :sort, #sortdir]
[#item.type, #item == #sortcol && [:sort, #sortdir]]
=>
# if #item.type is blank, so class is still empty
# if #item.type is "numeric" class is "numeric"
class = #item.type
# if #item equal #sortcol
# class will append "sort" and #sortdir if it is not empty.
if #item == #sortcol
class += "sort"
class += #sortdir
end
This construction #item == #sortcol && [:sort, #sortdir] will return [:sort, #sortdir] only if #item == #sortcol is true

Resources