Instance variable getting reset after subsequent calls - ruby-on-rails

I am new to ROR.
I have a controller
class Controllername < application
def method1
#obj = API_CALL
redirect_to redirect_url #calls the API authorization end point
#and redirects to action method2
end
def method2 #redirection to this action
#obj.somemethod #this value is null
end
end
My problem is when I use Instance variable or class varaible #obj or ##obj becomes nil in the action method2. I want this value to be whatever the value in method1.
Note: SESSION note helping as it's giving SSL error.
Any help is kindly appreciated.

Of cause using an instance variable doesn't work because the instance of the class only exists inside the method1 or method2 method .
What you can do is using class variables. You can set them using class_variable_set(:##class_variable_name, value) and get them using class_variable_get(::##class_variable_name) again. In your case it whould look like this:
class Controllername < application
def method1
class_variable_set(:##api_call_data, API_CALL)
redirect_to redirect_url #calls the API authorization end point
#and redirects to action method2
end
def method2 #redirection to this action
class_variable_get(:##api_call_data).somemethod #this value is null
end
end
Of cause this only works if the data is the same to every user if the data is user specific you need to use a class variable name that is user specific.

Related

Rails using private and protected methods in a Service object

I'm trying to move some business logic out of one of my controllers, StoreController and into a new Store::CreateService service object. Learning about services recently, it doesn't seem to be much of an established pattern for implementing them. I'm running into an error trying to call a protected method. I can obviously move the logic from those protected methods directly into execute but my understanding was that this should be okay to Rails.
undefined local variable or method `find_and_set_account_id' for #<Store::CreateService:0x00007f832f8928f8>
Here is the Service object
module Store
class CreateService < BaseService
def initialize(user, params)
#current_user, #params = user, params.dup
end
def execute
#store = Store.new(params)
#store.creator = current_user
find_and_set_account_id
if #store.save
# Make sure that the user is allowed to use the specified visibility level
#store.members.create(
role: "owner",
user: current_user
)
end
after_create_actions if #store.persisted?
#store
end
end
protected
def after_create_actions
event_service.create_store(#store, current_user)
end
def find_and_set_account_id
loop do
#store.account_id = SecureRandom.random_number(10**7)
break unless Store.where(account_id: account_id).exists?
end
end
end
You have an extra end after def execute..end. That end closes the CreateService class. This means your protected methods are defined on the Store module.
Hence the missing method.

Set an instance variable app wide in Rails

In my Rails application I have a class that I want to initialize and then access it throughout my controllers. So the idea is that I set it via the application controller if it's not already been defined:
class ApplicationController < ActionController::Base
before_action :set_custom_class
# create an instance of customclass if doesn't exist
def set_custom_class
#custom_class ||= CustomClass.new
end
end
An example of the class:
class CustomClass
def initialize; end
def custom_method
#custom_method
end
def custom_method=(content)
#custom_method = content
end
end
If I then have a controller like:
class MyController < ApplicationController
def method_1
# set the custom_method value on my instance
#custom_class.custom_method('Some content')
# return the value I set above
#variable = #custom_class.custom_method
redirect_to :method_2
end
def method_2
# I should be able to retrieve the same value from that same instance
#variable = #custom_class.custom_method
end
end
What I'm finding is that when calling method_1 the #variable will return my content fine, but when calling method_2 AFTER method_1 (so the custom_method for the app wide #custom_class has been set) it's returning nil.
Why isn't the instance being retained? The #custom_class shouldn't be creating a new instance as it's already been set. So I can't understand why the value I have set gets lost when requesting it.
You witnessing such behaviour, because state of a controller is not preserved between requests. For example, imagine that current_user method sets #current_user for one request and returns the same user for another one.
Please, consider an option of using cookies or database for sharing state between requests.
Otherwise, a workaround would be setting a class variable of CustomClass, but I don't recommend to do it.
Looks like your before_action will re-instantiate the new object on every request. That means that since you aren't passing anything through to the class in Method2, it will come out as NULL.
Since you said app-wide, why not make it app-wide?
In config/application.rb,
module App
class Application < Rails::Application
def custom_class
#custom_class ||= CustomClass.new
end
end
end
in your application code,
Rails.application.custom_class

Call to action on the same controller

I am learning rails and I have a question
How can I call an action from another in the same controller?
def new
new_method()
end
private
def new_method
...
end
This would be the right way?
The parenthesis is optional in Ruby. But, one action receive a call from client and respond one output. Your private "action" is only a function or method.
class User
def create
make_something(params)
end
private
def make_something(params)
#some implementation
end
end

Adding custom internal method to a controller

I'm new with RoR and I have a controller (UsersController) where I wish to verify the existence of a certain session before anything. Since the session verification code is the same for several methods and I don't want to repeat myself, I decided to make a new method in my controller to check the sessions:
class UsersController < ApplicationController
def index
end
def show
end
def new
if self.has_register_session?
# Does something
else
# Does something else
end
end
def edit
end
def create
end
def update
end
def destroy
end
def self.has_register_session?
# true or false
end
end
And when I run the page /users/new, I got this error:
undefined method `has_register_session?' for #<UsersController:0x1036d9b48>
Any idea?
self when you define the method refers to the UsersController class object, but within the instance method new, self refers to the instance of UsersController.
You can either make your method an instance method:
def has_register_session?
# code
end
You can then get rid of the self when calling has_register_session? in new as well.
Or call the method on the class:
if UsersController.has_register_session?
# code
end
instead of referencing UsersController explicitly you could do self.class.
Note that you likely want the first solution: making has_register_session? an instance method.
By doing def self.blah you've created a class method whereas you want an instance method.
You might also want to make the method protected - all public methods are exposed as actions by default.

Accessing a variable declared in a controller from a model

I'm using the facebooker gem which creates a variable called facebook_session in the controller scope (meaning when I can call facebook_session.user.name from the userscontroller section its okay). However when I'm rewriting the full_name function (located in my model) i can't access the facebook_session variable.
You'll have to pass the value into your model at some point, then store it if you need to access it regularly.
Models aren't allowed to pull data from controllers -- it would break things in console view, unit testing and in a few other situations.
The simplest answer is something like this:
class User
attr_accessor :facebook_name
before_create :update_full_name
def calculated_full_name
facebook_name || "not sure"
end
def update_full_name
full_name ||= calculated_full_name
end
end
class UsersController
def create
#user = User.new params[:user]
#user.facebook_name = facebook_session.user.name
#user.save
end
end

Resources