I grouped some Timesheet objects together using activerecord
scope :grouped_by_user_with_total_time, lambda {
group(:user_id, :day).select('user_id, SUM(time_worked) AS time_total, day, editable, approvable, accepted, comments')
}
And after I did that, now when I try to call the approve method on the grouped objects I get the error
Couldn't find TimeSheet without an ID
And it highlights the third line in my method
def approve
#time_sheets = []
*t = TimeSheet.find(params[:time_sheets])**
if t.instance_of?(Array)
#time_sheets = t
else
#time_sheets << t
end
successful = []
unsuccessful = []
#time_sheets.each do |timesheet|
unless timesheet.approved
timesheet.approve
if timesheet.save
successful << timesheet
else
unsuccessful << timesheet
end
end
end
I'm not very experienced with this and I am not sure how to check if my params[:time_sheets] is nil which might be the issue. Any help is appreciated.
Yes params[:time_sheets] being passed as nil would cause this error.
def approve
if params[:time_sheets]
#time_sheets = []
*t = TimeSheet.find(params[:time_sheets])**
if t.instance_of?(Array)
#time_sheets = t
else
#time_sheets << t
end
successful = []
unsuccessful = []
#time_sheets.each do |timesheet|
unless timesheet.approved
timesheet.approve
if timesheet.save
successful << timesheet
else
unsuccessful << timesheet
end
end
end
end
By adding a check with if params[:time_sheets] we can ensure the method only runs if the params[:time_sheets] is not nil. However it seems that you might be having a problem in passing your params. If you post your code where you show where you pass the params we could find out why it's passing nil.
Related
set_bonus(member_id, cookie) method does not work. I'm trying to update the same model that that the self.set_signup_attribution(member_id, cookie, origin) returns.
The new_has_value variable returns {"currency"=>"usd", "type"=>"flat", "amount"=>1000}
Model.rb
# THIS METHOD WORKS
def self.set_signup_attribution(member_id, cookie, origin)
return unless cookie.present?
tracking_code = cookie
attribution_channel = AttributionChannel.find_by tracking_code: tracking_code
associated_member_record = Member.find member_id
if attribution_channel.present?
Attribution.create!({
event: Attribution::SIGN_UP,
attribution_channel: attribution_channel,
associated: associated_member_record,
extra: origin
})
set_bonus(member_id, cookie)
else
Rails.logger.info "Unknown Attribution Channel for tracking code: '#{ tracking_code }'"
end
end
# THIS METHOD DOES NOT WORK. UPDATES THE DATABASE.
def self.set_bonus(member_id, cookie)
epoch = Member.find_by(id: member_id).attribution_epoch
attribution_code = AttributionChannel.find_by(tracking_code: cookie)
duration_value = attribution_code.attribution_duration.downcase.split(' ')
duration = duration_value.first.to_i.send(duration_value.last)
return if cookie.present? && epoch.present?
current_time = Time.now
if attribution_code.bonus_config.present?
if (current_time - epoch).to_i < duration
hash_value = attribution_code.bonus_config
new_hash_value = hash_value.assoc("sign_up")[1]
value = Attribution.where(attribution_channel_id: attribution_code)
if new_hash_value["type"] == "flat"
value.update_all(
bonus_amount: new_hash_value["amount"],
bonus_currency: new_hash_value["currency"]
)
elsif new_hash_value["type"] == "percentage"
value.update_all(
bonus_amount: new_hash_value["amount"],
bonus_currency: new_hash_value["currency"]
)
else
{
bonus_amount: "Doesn't exist",
bonus_currency: "Doesn't exist"
}
end
else
"Do nothing"
end
else
"Do nothing"
end
#cookie = nil
binding.pry
end
Controller.rb
def index
unless session[:just_signed_up]
redirect_back_or_settings_page
end
Attribution.set_signup_attribution(current_user, cookies[:visit_attr], request.referer)
Attribution.set_bonus(current_user, cookies[:visit_attr])
session[:just_signed_up] = false
#email = current_user.email
end
How do I go about this? That is what I have tried and doesn't work. Can I merge set_bonus method to set_signup_attribution method or something?
Any help will be appreciated.
So drilling this further:
I merged set_bonus with set_signup_attribution and the two fields (bonus_amount and bonus_currency) which set_bonus method is supposed to update returns nil:
Attribution.create!(
{
event: Attribution::SIGN_UP,
attribution_channel: attribution_channel,
associated: associated_member_record,
extra: origin
}.merge(self.set_bonus(member_id, cookie).to_h)
)
With this drill after using binding.pry on that set_bonus method, I figured out it worked but it's returning nil and I don't know why. Could it be because member_id is not available in the model or something?
in your if statement you should call set_bonus method on appropriate object.
attribution = Attribution.create!({
event: Attribution::SIGN_UP,
attribution_channel: attribution_channel,
associated: associated_member_record,
extra: origin
})
attribution.set_bonus(member_id, cookie) if attribution.persisted?
Just be careful as .create! will raise an error in case there is something wrong, so maybe would be better to use
attribution = Attribution.new(.....)
if attribution.save
attribution.set_bonus(.....)
else
Rails.logger.info attribution.errors
end
I hope this would help.
Cheers
Hi I create a controller Game to display a Q/A game
And I am blocked with <<, here is the code
def play
lvlup(lvl)
if lvl == 1
set_questions
else
get_questions
end
#answers = Answer.where.not(id: question.answer_id).limit(2).order("RANDOM()")
#answer ||= []
#answers << question.answer
#answers = #answers.shuffle
render 'play'
end
I create an array and I put the related answer in the global answers I want to display 4 Max.
Why does the undefined is here?
Here is the total code
class GamesController < ApplicationController
attr_accessor :lvl
def welcome
end
def congrat
end
def play
lvlup(lvl)
if lvl == 1
set_questions
else
get_questions
end
#answers = Answer.where.not(id: question.answer_id).limit(2).order("RANDOM()")
#answer ||= []
#answers << question.answer
#answers = #answers.shuffle
render 'play'
end
def loose
#question = Question.find(params[:question])
flash.now[:alert] = "Miss..."
render 'loose'
end
def check
#lvl = params[:lvl].to_i
answer_id = params[:id].to_i
question = Question.find(params[:question])
if #lvl == lvlmax
render action: 'congrat' and return
elsif answer_id == question.answer_id
flash.now[:notice] = "Well done !"
play
else answer_id != question.answer_id
loose
end
end
private
def lvlup(value)
#lvl = 1 + value.to_i
end
def lvlmax
#lvlmax = Question.all.count
end
def set_questions
#questionsids = []
Question.all.shuffle.each do |d|
#questionsids << d.id
end
cookies[:questions] = #questionsids
end
def get_questions
#questions = cookies[:questions].split('&')
end
def questions
#questions = cookies[:questions]
end
def question
#question = Question.find(questions[lvl])
end
end
Thank you for your help.
You are trying to append to the #answers result - this is an ActiveRecord relation, you cannot append data to that array.
Add .to_a in the end of your line where you set #answers to allow you to append to the array.
#answers = Answer.where.not(id: question.answer_id).limit(2).order("RANDOM()").to_a
mtrolle's answer might be correct, but I have my doubts as to why ActiveRecord::Relation was not returned as Array by default. (Also as mentioned by BroiStatse in his comment.)
I too noticed the same problem with my local setup however it was attributed to another issue all together. I am sharing this here in case you too happen to use MySQL.
Answer.where.not(id: question.answer_id).limit(2).order("RANDOM()")
returns an ActiveRecord::Relation object. And it translates to following SQL:
SELECT `answers`.* FROM `answers` WHERE (id != ID) ORDER BY RANDOM() LIMIT 2
When I try running the same in MySQL, I get:
ERROR 1305 (42000): FUNCTION database.RANDOM does not exist
Apparently MySQL does not have RANDOM() function, instead it uses RAND().
Converting ActiveRecord query accordingly returned correct Array to me:
Answer.where.not(id: question.answer_id).limit(2).order("RAND()")
I want to assign a confirmation code to my users while creating one. And I also titleize some columns before saving-updating them. So my user.rb looks like this (it may be a bit messy):
// user.rb
*** some code ***
before_save { titleize_column(:name)
titleize_column(:surname)
capitalize_column(:complaints)
capitalize_column(:education)
capitalize_column(:job)
capitalize_column(:complaintsdetails)
capitalize_column(:prediagnosis)
capitalize_column(:existingdiagnosis)
capitalize_column(:knownilnessesother)
capitalize_column(:usedmedicine)
capitalize_column(:operation)
capitalize_column(:trauma)
capitalize_column(:allergy)
capitalize_column(:otherhabits)
capitalize_column(:motherother)
capitalize_column(:fatherother)
capitalize_column(:siblingsother)
}
before_save :generate_confirmation_code
protected
def generate_confirmation_code
unless self[:confirmed]
if(self[:type] == 'Patient')
update_attribute :confirmation_code, SecureRandom.urlsafe_base64(20)
update_attribute :confirmed, false
else
update_attribute :confirmed, true
end
end
end
protected
def capitalize_column(attr)
unless self[attr].nil?
self[attr] = Unicode::capitalize self[attr]
end
end
protected
def titleize_column(attr)
unless self[attr].nil?
words = self[attr].split
words.each_with_index do |v,i|
words[i] = Unicode::capitalize v
end
self[attr] = words.join(" ")
end
end
I'm using separate methods for titleizing and capitalizing columns because they may be nil when first creating a user, so I'm checking if it is null or not in those methods. This structure works fine on a normal signup with strong parameters. However, if I try to use twitter signup with the method below, it gives me the error 'stack level too deep' and I can see that it calls the generate_confirmation_code 123 times from the application trace and then these happens:
app/models/user.rb:83:in each'
app/models/user.rb:83:ineach_with_index'
app/models/user.rb:83:in titleize_column'
app/models/user.rb:20:inblock in '
app/models/user.rb:64:in generate_confirmation_code' (x123 times)
app/models/user.rb:101:infrom_omniauth'
app/controllers/socials_controller.rb:4:in `create'
// method for signing up/logging in a user from twitter
class << self
def from_omniauth(auth_hash)
if exists?(uid: auth_hash['uid'])
user = find_by(uid: auth_hash['uid'])
else
user = find_or_create_by(uid: auth_hash['uid'], provider: auth_hash['provider'], type: 'Patient')
user.password_digest = User.digest('111111')
user.name = auth_hash['info']['name']
user.location = get_social_location_for user.provider, auth_hash['info']['location']
user.avatar = auth_hash['info']['image']
user.url = get_social_url_for user.provider, auth_hash['info']['urls']
user.save! // THIS IS THE LINE 101!
conversation = Conversation.create()
user.conversation = conversation
admin = Admin.first
admin.conversations << conversation
user.progress = Progress.create(active_state:1)
end
user
end
I think I'm messing up by using before_save not properly, but do not know how to do it right. What am I doing wrong here?
update_attribute also fires the save callbacks, thereby looping the before_save infinitely, thus producing stack level too deep.
You can just simply assign values in a before_save callback methods, because they will simply be saved afterwards anyway. See the following:
def generate_confirmation_code
unless self[:confirmed]
if(self[:type] == 'Patient')
self.confirmation_code = SecureRandom.urlsafe_base64(20)
self.confirmed = false
else
self.confirmed = true
end
end
end
You are calling update_attribute inside before_save callback method, instead you can just assign values to attributes. The method signature generate_confirmation_code should be like below -
def generate_confirmation_code
unless self[:confirmed]
if(self[:type] == 'Patient')
self.confirmation_code = SecureRandom.urlsafe_base64(20)
self.confirmed = false
else
self.confirmed = true
end
end
end
I am having a problem that when ever I call the update function it throws an error. I have tried to find the solution but I could'nt find it and I can't understad the error. Please tell me what is wrong with the code
The update function is called from this function
def bookmark_request
data = params[:d]
request_bookmarked = Request.getRequest(data)
bookmarked_against_Request = Request.first
request_bookmarked_2 = request_bookmarked
bookmarked_against_Request_2 = bookmarked_against_Request
if bookmarked_against_Request_2[:favourites]
bookmarked_against_Request_2[:favourites] << bookmarked_against_Request[:id]
else
bookmarked_against_Request_2[:favourites] = Array.new
bookmarked_against_Request_2[:favourites] << bookmarked_against_Request[:id]
end
Request.updateRequest(bookmarked_against_Request , bookmarked_against_Request_2)
redirect_to :action => "active"
end
and the update code is this
def updateRequest(request,req_data)
if request.update(req_data)
request
end
end
The error that I am getting is this
**NoMethodError at requests/bookmark_request
undefined method `empty?' for Request:0x007f3fa44c59b0**
The error always comes on the line if request.update(req_data)
Sice I do not have a reputation of 10 so I am posting links to screenshot of the error
http://tinypic.com/r/whbiv7/8
update() method's argument is expected to be a hash. But your req_data argument becomes actually a Request here:
def bookmark_request
bookmarked_against_Request = Request.first
...
bookmarked_against_Request_2 = bookmarked_against_Request
...
end
And Request class has no empty? method. Moreover it might become nil, if there are no Requests at all.
I call this method (with helper method detailed below as well), defined in User.rb model
def get_random_items
return nil unless groups_as_member
if groups_as_member == 1
assignments = groups_as_member.assignments.limit(5)
random_items = Post.rand_by_post(assignments)
end
random_groups = groups_as_member.sort_by{rand}.slice(0,5)
random_items = Array.new
i=0
return unless random_groups
until i == 10 do
random_groups.each do |group|
assignments = group.assignments.limit(5)
if y = Post.rand_by_post(assignments)
random_items << y
i+=1
if random_items == 5
return random_items
end
else
return random_items
end
end
end
return random_items
end
helper method rand_by_post in Post.rb
def self.rand_by_post(assignments)
find_by_id(assignments.rand.post_id)
end
in the user controller show action:
def show
#public_groups = Group.public
#groups_member = #user.groups_as_member
#groups_as_owner = #user.groups_as_owner
#random_items = #user.get_random_items
end
when I comment out the call in the user show action, the user show works fine on my development and production server. But when I try to user the method the servers will just hang there, not doing anything. I can't find any errors in the server logs or the heroku logs. My test writing skills are pretty limited, and I am having trouble writing one for the entire method.
Can anyone spot a problem?
if your random_groups is empty, your helper method get_random_items will go into an endless loop until i == 10 do ... end. That could be the reason.
You might want to change return unless random_groups to return if random_groups.empty?