update function throwing erro(rails) - ruby-on-rails

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.

Related

updating the database after create action doesn't work

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

Rails.cache.fetch does not work for array of json

I am trying to cache server API response using Rail.cache.fetch feature but it seems like just always 'nil' instead cached data. Method below runs one time, then always fails with 'access to nil class' kind error when I am trying to go through #my_api_data_ variable
def index
api_statuses_
end
def api_statuses_
Rails.cache.fetch('api_repsonse_m_', expires_in: 3.minute) do
#mypairs_ = ['ticker1','ticker2', 'ticker3', 'ticker4', 'ticker5', 'ticker6', 'ticker7', 'ticker8', 'ticker9', 'ticker10']
#my_api_data_ = []
#my_api_data_poplr = []
url = 'https://myserver.com/ticker/'
#mypairs_.each do |item_|
uri = URI(url + item_)
response = Net::HTTP.get(uri)
begin
#response is like this {"status":"valu1","time":"valu2","data":"valu3"}
myresult = JSON.parse(response)
rescue JSON::ParserError
end
#Rails.logger.info myresult
#my_api_data_.push(myresult);
end
end
end
I hope maybe someone knows why it goes bad each time
I tried to add line "#my_api_data_" right before the end of cache block. This is the same error I got on original circumstances:
I, [2018-01-13T19:29:14.384766 #5716] INFO -- : Processing by Private::MydataController#index as HTML
I, [2018-01-13T19:29:14.403774 #5716] INFO -- : Rendered private/mydata/index.html.slim within layouts/mydatalayout_ (0.7ms)
I, [2018-01-13T19:29:14.403919 #5716] INFO -- : Completed 500 Internal Server Error in 19ms
F, [2018-01-13T19:29:14.405077 #5716] FATAL -- :
ActionView::Template::Error (undefined method `each' for nil:NilClass):
37: .row
38: /! Top head coin-boxes
39: .market-top-coin-boxes
40: - #my_api_data_.each do |pair_data|
It seems that the problem here is that you have to return #my_api_data_ at the end of the block. Let check the code below:
def api_statuses_
Rails.cache.fetch('api_repsonse_m_', expires_in: 3.minute) do
#mypairs_ = ['ticker1','ticker2', 'ticker3', 'ticker4', 'ticker5', 'ticker6', 'ticker7', 'ticker8', 'ticker9', 'ticker10']
#my_api_data_ = []
#my_api_data_poplr = []
url = 'https://myserver.com/ticker/'
#mypairs_.each do |item_|
uri = URI(url + item_)
response = Net::HTTP.get(uri)
begin
#response is like this {"status":"valu1","time":"valu2","data":"valu3"}
myresult = JSON.parse(response)
rescue JSON::ParserError
end
#Rails.logger.info myresult
#my_api_data_.push(myresult);
end
#my_api_data
end
end
Note that the first time that you call the api_statuses_ method all the blocked will be executed, and the return value will be written to the cache under the api_repsonse_m_ key. So, the next time that you call api_statuses_, and if the time in expires_in has not expired, it will return the value save in the cache and the block will not be executed.
Also, could you show us where and how are you using this method? Showing the code and the error log could be great to understand the problem.
Updated: It seems that you are not using correctly this. You should call the api_statuses_ method in the index method under the MydataController controller, and save the return value to a variable that will be use in your view.
For instance:
module Private
class MydataController
def index
#api_statuses = api_statuses_
end
end
end
Then, in your view:
.row
.market-top-coin-boxes
- #api_statuses.each do |pair_data|
Why are you using '#my_api_data_' in the view??
use
def index
#result = api_statuses_
end
use #result in your view files. Note, if there is a cache hit the block passed to the Rails.cache.fetch is not run.

Issue with taking params

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.

How can I work with this Module/Class setup?

I have the following module/class:
module Pigeons
class FedEx
attr_accessor :signature_name
def initialize(account)
self.account = account
end
def response(number)
body = "...some xml..."
return HTTParty.post('http://example.com', :body => body)
end
def track(number)
details = response(number)
self.signature_name = details[:delivery_signature_name]
end
end
end
What I'd like to be able to do is this:
#fedex ||= Pigeons::FedEx.new('123abc')
tracker = fedex.track('1234567890')
tracker.signature_name
Everything is working up until the tracker.signature_name part, which throws an undefined method 'signature_name' for nil:NilClass error.
The problem is in this line:
self.signature_name = details[:delivery_signature_name]
details[:delivery_signature_name] turns out to be nil, which is then assigned to self.signature_name and then becomes return value of track method. And here
tracker = fedex.track('1234567890')
tracker.signature_name
tracker will be nil and you try to call a method on it.
You probably meant to write this instead:
def track(number)
details = response(number)
self.signature_name = details[:delivery_signature_name]
self # <== here
end
You need two methods called signature_name= and response that do whatever they are supposed to do in your class.

RubyAmf and Rails 3

I have recently been trying to upgrade my app form Rails 2.3.8 to newly-releases Rails 3.
After going through fixing some Rails 3 RubyAMF doesn't seem to work:
>>>>>>>> RubyAMF >>>>>>>>> #<RubyAMF::Actions::PrepareAction:0x1649924> took: 0.00017 secs
The action '#<ActionDispatch::Request:0x15c0cf0>' could not be found for DaysController
/Users/tammam56/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.0/lib/abstract_controller/base.rb:114:in `process'
/Users/tammam56/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.0/lib/abstract_controller/rendering.rb:40:in `process'
It doesn't seem to be able to find the proper controller. Might have to do with new changes in Rails 3 Router. Do you know how to go about finding the root cause of the problem and/or trying to fix it?
I'm pasting code from RubyAMF where this is happening (Exception happens at the line: #service.process(req, res)):
#invoke the service call
def invoke
begin
# RequestStore.available_services[#amfbody.service_class_name] ||=
#service = #amfbody.service_class_name.constantize.new #handle on service
rescue Exception => e
puts e.message
puts e.backtrace
raise RUBYAMFException.new(RUBYAMFException.UNDEFINED_OBJECT_REFERENCE_ERROR, "There was an error loading the service class #{#amfbody.service_class_name}")
end
if #service.private_methods.include?(#amfbody.service_method_name.to_sym)
raise RUBYAMFExc
eption.new(RUBYAMFException.METHOD_ACCESS_ERROR, "The method {#{#amfbody.service_method_name}} in class {#{#amfbody.service_class_file_path}} is declared as private, it must be defined as public to access it.")
elsif !#service.public_methods.include?(#amfbody.service_method_name.to_sym)
raise RUBYAMFException.new(RUBYAMFException.METHOD_UNDEFINED_METHOD_ERROR, "The method {#{#amfbody.service_method_name}} in class {#{#amfbody.service_class_file_path}} is not declared.")
end
#clone the request and response and alter it for the target controller/method
req = RequestStore.rails_request.clone
res = RequestStore.rails_response.clone
#change the request controller/action targets and tell the service to process. THIS IS THE VOODOO. SWEET!
controller = #amfbody.service_class_name.gsub("Controller","").underscore
action = #amfbody.service_method_name
req.parameters['controller'] = req.request_parameters['controller'] = req.path_parameters['controller'] = controller
req.parameters['action'] = req.request_parameters['action'] = req.path_parameters['action'] = action
req.env['PATH_INFO'] = req.env['REQUEST_PATH'] = req.env['REQUEST_URI'] = "#{controller}/#{action}"
req.env['HTTP_ACCEPT'] = 'application/x-amf,' + req.env['HTTP_ACCEPT'].to_s
#set conditional helper
#service.is_amf = true
#service.is_rubyamf = true
#process the request
rubyamf_params = #service.rubyamf_params = {}
if #amfbody.value && !#amfbody.value.empty?
#amfbody.value.each_with_index do |item,i|
rubyamf_params[i] = item
end
end
# put them by default into the parameter hash if they opt for it
rubyamf_params.each{|k,v| req.parameters[k] = v} if ParameterMappings.always_add_to_params
begin
#One last update of the parameters hash, this will map custom mappings to the hash, and will override any conflicting from above
ParameterMappings.update_request_parameters(#amfbody.service_class_name, #amfbody.service_method_name, req.parameters, rubyamf_params, #amfbody.value)
rescue Exception => e
raise RUBYAMFException.new(RUBYAMFException.PARAMETER_MAPPING_ERROR, "There was an error with your parameter mappings: {#{e.message}}")
end
#service.process(req, res)
#unset conditional helper
#service.is_amf = false
#service.is_rubyamf = false
#service.rubyamf_params = rubyamf_params # add the rubyamf_args into the controller to be accessed
result = RequestStore.render_amf_results
#handle FaultObjects
if result.class.to_s == 'FaultObject' #catch returned FaultObjects - use this check so we don't have to include the fault object module
e = RUBYAMFException.new(result['code'], result['message'])
e.payload = result['payload']
raise e
end
#amf3
#amfbody.results = result
if #amfbody.special_handling == 'RemotingMessage'
#wrapper = generate_acknowledge_object(#amfbody.get_meta('messageId'), #amfbody.get_meta('clientId'))
#wrapper["body"] = result
#amfbody.results = #wrapper
end
#amfbody.success! #set the success response uri flag (/onResult)
end
The best suggestion is to try rails3-amf. It currently is severely lacking in features in comparison to RubyAMF, but it does work and I'm adding new features as soon as they are requested or I have time.

Resources