Standalone class generating method_missing - ruby-on-rails

In a Rails application an ad hoc class is defined
class TwitterClient
BASE_URL = "https://api.twitter.com/2/"
def initialize(twitter_account)
#twitter_account = twitter_account
Rails.logger.info(#twitter_account.inspect)
end
def me
path = BASE_URL.to_s + 'users/me'
get(path)
end
private
def get(path)
request(:get, path)
end
end
Verifying via the console, an object can be created
c = TwitterAccount.first
=>
#<TwitterAccount:0x00000001086c5c10
however, calling the me method on that object c.me returns an error:
.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/activemodel-7.0.4/lib/active_model/
attribute_methods.rb:458:in `method_missing': undefined method `me' for #<TwitterAccount
Where is this mistake?

I may as well stick it as an answer to help other devs stuck out there,
c does not seem to be an instance of TwitterClient but of TwitterAccount. If you want to have access to a method in the TwitterClient class you need to create an instance of it:
twitter_client = TwitterClient.new(twitter_account)
then you can access the me method like:
twitter_client.me

Related

Rails not registering API call variable

I have a simple API called wrapped in my lib/
lib/riotapi.rb
class RiotApi
riot_url = 'https://na.api.pvp.net/api/lol/na/v1.4/summoner/by-name/RiotSchmick?api_key=ENV['mykey']'
def unique_url
response = HTTParty.get(riot_url)
json = JSON.parse(response.body)
json
end
end
my controller
class WelcomeController < ApplicationController
require 'riotapi'
def index
api = RiotApi.new()
#list = api.unique_url
end
end
I have my welcome#index as the index page of the application. When I open it up, it says that undefined local variable or method "riot_url"
What am I doing wrong here?
Edit: The above sample is taken from here
Very Basic Rails 4.1 API Call using HTTParty
You should use a ruby constant (ALL CAPITAL) for this:
lib/riotapi.rb
class RiotApi
RIOT_URL = 'https://na.api.pvp.net/api/lol/na/v1.4/summoner/by-name/RiotSchmick?api_key=ENV['mykey']'
def unique_url
response = HTTParty.get(RIOT_URL)
JSON.parse(response.body)
end
end
Also note that you do not have to use the json variable in your unique_url
Here's is a SO answer that goes over the variable scope in a class. Note that I chose a ruby constant since I assumed the url will not changed. If you have a method in your class that changes the url, you should use a class variable (the one with ##)

Rails model definition using related field

I have a Rails app that is multi-tenant. In the Tenant record, I store codes that are particular to that Tenant.
The following works well (PS - scope doesn't work):
class Worequest < ActiveRecord::Base
acts_as_tenant(:tenant)
def self.closed
where("statuscode_id = ?", ActsAsTenant.current_tenant.request_closed)
end
What I really need is not worequest.statuscode_id but instead worequest.statuscode.position.
I tried this:
def self.closed
self.statuscode.position = ActsAsTenant.current_tenant.request_closed
end
But, that gives this error:
undefined method `statuscode'
Thanks for the help!
Your method is a class method. It means that your code is referring to the class via self object.
def self.closed
self.statuscode.position = ActsAsTenant.current_tenant.request_closed
end
self here is class Worequest and it doesn't have an attribute statuscode.
What are you trying to with self.statuscode.position = ActsAsTenant.current_tenant.request_closed?

Can't access class variable in ruby/rails?

I have a class like so:
Railsapp/lib/five9_providers/record_provider.rb:
class Five9Providers::RecordProvider < Five9Providers::BaseProvider
def add_record_to_list
variable = 'test'
end
end
Then, in a controller I have this:
Railsapp/app/controllers/five9_controller.rb:
class Five9Controller < ApplicationController
def import
record_provider = Five9Providers::RecordProvider.new()
record_provider.add_record_to_list
puts Five9Providers::RecordProvider::variable
end
end
However, calling my controller method import just returns:
NoMethodError (undefined method 'variable' for Five9Providers::RecordProvider:Class)
How can I access variable from the recover_provider.rb class in my five9_controller.rb class?
EDIT:
Even when using ##variable in both my record_provider and my five9_controller, I still can't access that variable. I am calling it like so: puts ##variable.
As written, you cannot. variable is local to the instance method and can't be accessed by any Ruby expression from outside the method.
On a related point, the term "class variable" is typically used to refer to variables of the form ##variable.
Update: In response to your "Edit" statement, if you change variable to ##variable in your class, then there are techniques available to access that variable from outside the class, but a naked reference to ##variable isn't one of them. Carefully read the answers to the question you cited in your comment for more information.
Best way is to set and get the value using methods. Below is a sample code
class Planet
##planets_count = 0
def initialize(name)
#name = name
##planets_count += 1
end
def self.planets_count
##planets_count
end
def self.add_planet
##planets_count += 1
end
def add_planet_from_obj
##planets_count += 1
end
end
Planet.new("uranus")
Plant.add_planet
obj = Planet.new("earth")
obj.add_planet_from_obj

call an class method given an instance in ruby

I'm using rails ActiveModel, I defined 2 methods like this:
def find_existing_task(task)
existing_one = Task.find(task.id)
end
def find_existing_person(person)
existing_one = People.find(person.id)
end
But I think I need a more generic method like this:
def find_existing(any_active_model_instance_with_id)
existing_one = ActiveModelClass.find(any_active_model_instance_with_id.id)
end
But I don't know how to call the class method given an instance, in above, given task, I can call Task.find without specifing class name "Task"
Any solution? thanks!
You can do it with the following code
def find_existing(some_model)
existing_one = some_model.class.find(some_model.id)
end

In Rails, I'm getting a NoMethodError when calling function in new model

I have a model called Action. It looks like this:
class Action < ActiveRecord::Base
def register_action(email,type)
#action = new()
#action.guid = "123456789"
#action.email = email
#action.action = type
action.guid if #action.save
end
end
If I try and access this class from my user_controller, I get an error.
The code I'm trying to use is :
if (#User.save)
guid = Action.inspect()
guid = Action.register_action(#User.email,"REGISTER")
MemberMailer.deliver_confirmation(#User,guid)
end
Action.inspect() works fine, so I'm guessing that the Action class can be seen, but the line which calls register_action returns the following error:
NoMethodError in UserController#createnew
undefined method `register_action' for #<Class:0x9463a10>
c:/Ruby187/lib/ruby/gems/1.8/gems/activerecord-2.3.8/lib/active_record/base.rb:1994:in `method_missing'
E:/Rails_apps/myapp/app/controllers/user_controller.rb:32:in `createnew'
What am I doing wrong?
I'm new to Rails so apologies for being stupid.
Problem is on this line:
guid = Action.register_action(#User.email,"REGISTER")
register_action is an instance method, not a class method, so you call it on an instance of the Action class, not the Action class itself.
If you want to define register_action as a class method, you should do so like this:
def self.register_action(email, type)
# ... Body ...
end
Change
def register_action(email,type)
to either
def self.register_action(email,type)
or
def Action.register_action(email,type)
In your register_action method you need to do #action = Action.new instead of #action = new(). Alternatively, you can construct it like this:
#action = Action.new(:guid => "123456789", :email => email, :action => type)
Also, you have defined register_action as an instance method on your Action class, but you're calling it as a class method by using Action.register_action. Change it to:
def self.register_action(email, type)
...
end

Resources