How to create this model meta method? - ruby-on-rails

I used to have the following model method, which I called upon using if #invitation.invite_expired? ...:
def invite_expired?
cycle_invite_sent_at < 2.hours.ago
end
Because I want to use this method for multiple expiration checks I have tried to create a "meta" method as follows:
def expired?(what)
check = send("#{what}_invite_sent_at")
check < 2.hours.ago #Also tried "self.check" but that made no difference.
end
I call upon this method using: if #invitation.expired?(cycle) .... However, now all sorts of tests fail with the message:
NameError: undefined local variable or method `cycle' for #<InvitationsController:0x0000000a5e8d50>
Does anyone see what I'm doing wrong here?

You should use it like:
if #invitation.expired?("cycle")
# some code here.
I assume this because undefined local variable or method 'cycle' raised in the controller code, it happens, when you try to use plain cycle instead of a string "cycle".

Related

Undefined method when calling model method in controller

I have a class method in my User model:
def self.method_name
...
end
In a controller, I need to call this method on a User instance obtained through association:
#user = game_play.player.user
As expected, it threw a no method error because it's a class method.
What is the way to call the method in this case?
EDIT: Adding code for question clarification
#user = #game_play.client.user.
#token = #user.set_login_bypass_token
My model:
def set_login_bypass_token
#We generate a raw token and an encrypted version of the same token
raw, enc = Devise.token_generator.generate(User, :login_bypass_token)
self.login_bypass_token = enc
self.login_bypass_token_set_at = Time.now
self.save(validate: false)
#Raw token is sent to the user via email to provide auto-login
raw
end
The error:
PG::UndefinedColumn: ERROR: column users.login_bypass_token does not exist
Notice the error has it as users.login_bypass_token instead of set_login_bypass_token
EDIT:
My first answer was before you mentioned Devise and assuming you didn't know if you needed a class or instance method. It's clear that your method must be an instance one.
I think you are trying to apply something you found here: https://stackoverflow.com/a/30857087/3372172
This requires that you add a new field to the users database, to manage the :login_bypass_token. Because you will use this column later to perform a find_by. Devise does not add this column to the database.
PREVIOUS ANSWER
If the method needs to access instance variables (which means it acts differently depending the specific object in the User class), it should be an instance method, defined without the self keyword.
If it is a class method, it cannot depend on any attribute from a specific object, and you cannot call it from an instance of the class.
You must decide if it's really a class method or an instance method.
`
If you need a class method to be called from an instance, you can do this (but I don't know why you could need it).
class User
def self.method_name
# blablabla
end
def method_name
User.method_name
end
end
Should be using an instance method instead of a class method. I'm not sure how you would get an error where it's looking for an attribute on the model since those can only be defined in the schema. If you're adding a regular instance method within the model it should work correctly.

Use instance method in ActiveRecord where clause

I have an instance method that has logic I want to use in a query. My attempts have not worked. I'd rather not duplicate the logic inside is_thing when building my where clause.
class Foo < ActiveRecord::Base
def is_thing?
#... some logic
end
end
I tried
Foo.where(is_thing?)
and got
NoMethodError: undefined method `is_thing?' for main:Object
The Approach I would recommend
I do believe that method is not good practice (to chain a where query). It will only add unnecessary complexity.
The better approach is using scope
scope :is_thing?, -> { where(thing: true) }
and call it
Foo.is_thing?.where()
The Why
The reason it is returned
NoMethodError: undefined method `is_thing?' for main:Object
Is because is_thing? is instance variable of Foo
Instance variable can be called on an instance of the class. And not availabe on main object.
You, however could do
Foo.where(Foo.new.is_thing?)
It is posible to use that if you convert is_thing? to class method. e.g
def self.is_thing?
# code
end
and use it this way
Foo.where(Foo.is_thing?)
try this:
class Foo < ActiveRecord::Base
def is_thing?
#... some logic
end
def things
Foo.where('thing_check = ?', self.is_thing?)
end
end
create another instance method to wrap your where query. Then access it as Foo.last.things

NameError: undefined local variable or method `desired_preferences'

I have created a module with a method
module Adding_preferences
def desired_preferences
#preference = %w(motabilitySpecialist newCars bodyshop filter8 filter7).each do |selection|
#browser.label(:for, selection ).click
end
end
end
I have included this module into a class:
class Pages
include Adding_preferences
attr_accessor :browser, :preference
def initialize
#browser = Watir::Browser.new :ff
end
end
World do
Pages.new
end
I am calling this method in a Cucumber scenario
When /^I select a desired preference$/ do
desired_preferences
end
But at runtime I receive an error, "NameError: undefined local variable or method `desired_preferences'". Where am i going wrong?
When you include a module to a class you can use this method in the instance methods of this class. You cant call the included method in a View that displays the data from the model that includes the module. For me it looks like you just dont use the desired_preferences method in an instance method.
Please show us the peace of code you try to call the method if this still doesnt help you out.
// The naming of the Module is not conventional. You should call it module AddingPreferences isntead ofmodule Adding_preferences and the file should be named adding_preferences.rb then try to include AddingPreferences
It's a good idea for you to spend some time getting more familiar with Ruby's Class/Module/Object/Method inheritance model, because the way you're structuring your code there is a little bit messy.
However, a simple thing to try (and I'm not going to guarantee that it will work flawlessly) is the following modifications:
Assign your instantiated Pages class to a class instance variable:
World do
#page = Pages.new
end
...and then use that instance variable in your step definition...
When /^I select a desired preference$/ do
#page.desired_preferences
end
I hope that helps!

Mocha expects method

So my situation is:
I have a 2 modules that have the same structure like that:
module Module1
class Config
def fee_rate
2
end
end
end
So, say, Module2 would have class Config with the method fee_rate, just with a different value (those are actually implemented in a rails engine, but it shouldn't matter)
and then my model can use either Module1 or Module2 to get the fee rate value like that:
def config
#config ||= "#{module_name.titleize}::Config".constantize.new
#config
end
def get_value
config.get_fee * some_other_value
end
What I'm trying to test is if get_fee function was called on the correct class:
"#{model.module_name.titleize}::Config".constantize.any_instance.expects(:get_fee).at_least_once
model.get_value
and on the line when I call get_value I get the following error - undefined method `*' for nil:NilClass. I'm completely lost now, so I'd appreciate any help and ideas.
By setting up an expectation for get_fee you are preventing the actual method call from happening. Because you haven't set a return value for the expectation, e.g. expects(:get_fee).at_least_once.returns(3) it is returning nil, hence the error message.
You may have more success by doing away with the expectation altogether and checking that the right type of config class is created, e.g.
model.get_value
assert_equal "#{model.module_name.titleize}::Config".constantize,
model.config.class

Ruby NoMethodError

Ok, I'm a bit of a newb. I know this error is occuring because I don't properly understand something about how methods are called. So can you help me understand what is going wrong here?
NoMethodError in ThingController#index
undefined method `initialized?' for Thing::Backend:Class
From the erroring section of ThingController.rb:
class ThingController
def init_things
Backend.init_things unless Backend.initialized?
end
t = ThingController.new
t.init_things
end
inside Backend.rb
class Backend
# checks if the things hash is initialized
def initialized?
#initialized ||= false
end
# loads things
def init_things
puts "I've loaded a bunch of files into a hash"
#initialized = true
end
end
I'm not calling the method correctly and I cannot find any clear explanations for this error on the internet. Please help.
Thanks
It appears that the issue is that the initialized method that you have declared in Backend is an instance method. When you then call Backend.initialized? you are calling calling the class method initialized? for the Backend class. This method is not defined, and so it raises the NoMethodError. You can solve this by declaring the method using def self.initialized?. If you really want this to be a class method, you may need to consider how the rest of your code is organized.
You can find more information on class vs. instance methods at http://railstips.org/blog/archives/2009/05/11/class-and-instance-methods-in-ruby/
You've declared initialized? as an instance method but are calling it as if it were a class method. Here's an explanation of the difference between instance methods and class methods.

Resources