What is wrong in this ruby on rails method? - ruby-on-rails

My syntax error is solved, but now I've got another problem.
I have a model User and Post. Also i've created the additional model which is called Like(for likes/dislikes system). So, i wrote a method to check if the copy of the model Like has the given 'post_id' and 'user_id' simulteniously, then the given Post was liked by the given User. Here's the code of my method
def licked(p,u)#p - post, u - user
if Like.all.empty? then return false
else
if (Like.where(post_id: p.id).empty?)
return false
else
posts=Like.where(post_id: p.id)
if ((posts.length<2) && (posts[0].user_id==u.id) && (posts[0].action!=nil))==true then return true
else
if ((posts.length<2) && (posts[0].user_id!=u.id)&& (posts[0].action!=nil)) then return false
else posts.each do |i|
if (i.user_id==u.id&& (posts[0].action!=nil)) then return true
end
end
end
end
end
end
end
Sorry, if there are many if's, i did not find any other way to relize it, and anyway it's not working. So i'm asking for your help: either to hange the existing code or making it other way, thanks.

You don't need ANY of that logic.
def liked(post, user)
Like.where(user_id: user.id, post_id: post.id).where.not(action: nil).exists?
end

Related

cancan rails code understanding

I am unable to debug some of cancancan code and looking for some help.
can :update, Message do |m|
false
end
But strangely cancancan always return true and i am unable to debug the issue.Here is a small piece of relevant cancancan code
rule.rb
def matches_conditions?(action, subject, extra_args)
if
...
elsif #block && !subject_class?(subject)
#block.call(subject, *extra_args)
end
end
I can see that the #block.call is made and it return false but this piece of code in the ability.rb does not make sense to me
match = subject.map do |subject|
relevant_rules_for_match(action, subject).detect do |rule|
rule.matches_conditions?(action, subject, extra_args)
end
end.compact.first
match ? match.base_behavior : false
The base_behaviour is never set after initialization, and set to true at initialization, how would base_behaviour of a rule would ever return false.
The helper function is called
ability = Ability.new(user)
ability.can? :update ,#message
Got it there was a overriding ability

Rails application helper return if false

I'm writing a helper method to determine if current has any pending reviews to write. If there is a pending review, simply print a line in the view.
My helper is putting exactly the right stuff to the console, however I'm struggling with how to simply return it. In this scenario, current user has an id: 4.
My Code:
def review_pending
gallery = current_user.galleries.first
if gallery
if gallery.permissions.accepted
gallery.permissions.accepted.each do |p|
return true if p.user.reviews.find_by_reviewer_id(!current_user)
puts "already written review: #{p.user.reviews.find_by_reviewer_id(4)} - prints correctly"
end
end
end
end
My goal: if there is a user from the list that current user has not yet reviewed return true.
Thanks!!!
Thanks for all your pointers!
I had forgotten/learned 2 things to make it work:
First, if nil is returned, ruby returns the last returned value which in my case was true (if gallery.permissions.accepted).
Secondly, I placed the "!" before current_user, and should have placed it before the entire line.
Corrected Code:
def review_pending
gallery = current_user.galleries.first
if gallery
gallery.permissions.accepted.each do |p|
return !p.user.reviews.find_by_reviewer_id(current_user.id)
end
end
return false
end

Rails : Return an object to show user's profile completeness

I have a User Model and would like to return to the controller and view what parts of the user's profile are complete and what parts are not.
So it would return for example an object "profile_completeness" which can be used like so :
#user.profile_completeness.personal_info
Which would be true if the particular part of the profile was filled.
What I tried :
def profile_completeness
if self.name.present? && self.email.present?
profile_completeness.personal_info = true
end
return profile_completeness
end
I got the error :
SystemStackError: stack level too deep
Am I going about this the right way? If not, what do you think is the best
You can't call set the .personal_info=true on the method itself. In such situation I'd just use either Hashes.
def profile_completeness
ret = Hash.new
if self.name.present? && self.email.present?
ret[:personal_info] = true
end
ret
end
Or even better I'd prefer different method for each of the 'completeness' part:
def personal_info_complete?
....
end

Add value to :params[]

What i have: (Action in Controller)
def create
#test = Test.new(params[:test])
#test.save
devicefiles = params[:devicefiles]
if devicefiles != nil
devicefiles.each do |attrs|
devicenote = Testdevicenote.new(attrs, :test_id => #test.id)
devicenote.save
end
end
end
This controller action does not show any error message and is rendering the view, but :test_id is not being saved in the database. How can i solve this?
EDIT: Ok whoops, I see it now...
Models only take one hash on initialize, not 2.
Testobjectnote.new(attrs.merge(:test_id => #test.id))
In short no one here has any clue, because that's not enough information. We dont know how your models are setup.
But when debugging models that "won't save" it's often good to use the bang version save, save!. save returns true or false letting you know if it was able to save the record. But save! will raise exceptions when the model can't be saved, and the exception will tell you why.
That exception will likely tell you why the record is not being saved.
Also, its usually better to use the associations, rather than manage the ids yourself.
def create
#test = Test.new(params[:test])
if params[:devicefiles]
params[:devicefiles].each do |attrs|
#test.testdevicenotes << Testdevicenotes(attrs)
end
end
#test.save
end
It's hard to say because you didn't post your view with the form that is posting to the create action, but if it's a typical Rails form, it should probably look like:
def create
#test = Test.new(params[:test])
#test.save
devicefiles = params[:test][:devicefiles]
if devicefiles != nil
devicefiles.each do |attrs|
devicenote = Testdevicenote.new(attrs, :test_id => #test.id)
devicenote.save
end
end
objectfiles = params[:test][:objectfiles]
if objectfiles != nil
objectfiles.each do |attrs|
objectnote = Testobjectnote.new(attrs, :test_id => #test.id)
objectnote.save
end
end
end
This assumes that :devicefiles and :objectfiles are inside the form :test

Rails: How to check if "update_attributes" is going to fail?

To check if buyer.save is going to fail I use buyer.valid?:
def create
#buyer = Buyer.new(params[:buyer])
if #buyer.valid?
my_update_database_method
#buyer.save
else
...
end
end
How could I check if update_attributes is going to fail ?
def update
#buyer = Buyer.find(params[:id])
if <what should be here?>
my_update_database_method
#buyer.update_attributes(params[:buyer])
else
...
end
end
it returns false if it was not done, same with save. save! will throw exceptions if you like that better. I'm not sure if there is update_attributes!, but it would be logical.
just do
if #foo.update_attributes(params)
# life is good
else
# something is wrong
end
http://apidock.com/rails/ActiveRecord/Base/update_attributes
Edit
Then you want this method you have to write. If you want to pre check params sanitation.
def params_are_sanitary?
# return true if and only if all our checks are met
# else return false
end
Edit 2
Alternatively, depending on your constraints
if Foo.new(params).valid? # Only works on Creates, not Updates
#foo.update_attributes(params)
else
# it won't be valid.
end
The method update_attributes returns false if object is invalid. So just use this construction
def update
if #buyer.update_attributes(param[:buyer])
my_update_database_method
else
...
end
end
If your my_update_database_method has to be call only before update_attributes, then you shoud use merge way, probably like this:
def update
#buyer = Buyer.find(params[:id])
#buyer.merge(params[:buyer])
if #buyer.valid?
my_update_database_method
#buyer.save
else
...
end
end
This may not be the best answer, but it seems to answer your question.
def self.validate_before_update(buyer)#parameters AKA Buyer.validate_before_update(params[:buyer])
# creates temporary buyer which will be filled with parameters
# the temporary buyer is then check to see if valid, if valid returns fail.
temp_buyer = Buyer.new
# populate temporary buyer object with data from parameters
temp_buyer.name = buyer["name"]
# fill other required parameters with valid data
temp_buyer.description = "filler desc"
temp_buyer.id = 999999
# if the temp_buyer is not valid with the provided parameters, validation fails
if temp_buyer.valid? == false
temp_buyer.errors.full_messages.each do |msg|
logger.info msg
end
# Return false or temp_buyer.errors depending on your need.
return false
end
return true
end
you'd better check it in your model through a before_save
before_save :ensure_is_valid
private
def ensure_is_valid
if self.valid?
else
end
end
I've run into the same scenario - needed to know if record is valid and do some actions before update save. I've found out that there is assign_attributes(attributes) method which update method uses before save. So nowadays it's likely correct to do:
def update
#buyer = Buyer.find(params[:id])
#buyer.assign_attributes(params[:buyer])
if #buyer.valid?
my_update_database_method
#buyer.save
else
...
end
end

Resources