Setting global instance variable based on domain in Rails - ruby-on-rails

I have a single Rails application that is currently being accessed via lets say https://www.domain1.com and I would like to enable the application to be accessed by a second domain, lets say https://www.domain2.com which would then set a global instance variable.
I would then like to use this instance variable to control certain things on the page such as content, styles and images.
Any ideas how I could achieve this?

E.g.
def my_action
#domain_instance_variable = request.domain
$domain_global_variable = request.domain
end
A global variable and an instance variable are different things. An instance variable is scoped to an instance of a class, and a global variable has a global scope. It's a good rule of thumb to minimize scope.
In the case of Rails code in controllers, views or helpers, you can just call request.domain directly instead of assigning that to a variable.

Related

what controller data is accessible in html.erb?

I'm trying to understand how the controller class and the .html.erb view files in Rails are connected, and how the view accesses data in the controller methods. For example, I have the following controller class:
class SomeController < ApplicationController
def show
# defining some data to access in the view
x = 1
#y = 2
end
end
If in the corresponding .html.erb view file, I try to access #y, this works fine
<p> <%= #y %> </p>
However, if I try to access x, it gives an error
<p> <%= x %> </p>
undefined local variable or method 'x'
Conceptually, why #y is accessible in the .html.erb view, but x is not.
PS: I should add that I know variables with # indicate instance variables in Ruby, so (I think) #y would be an instance variable of the instance of SomeController. However, I'm unclear how this affects what .html.erb view file has access to from SomeController.
In RoR if you declare a variable in your controller as an instance variable #y it becomes available to your view.
On the other hand x is the local variable and is only accessible within it's scope.
This is a matter of scope (scope defines where in a program a variable is accessible). Ruby has four types of variable scope, local, global, instance and class.
In your case:
x is a local variable, they are local to the code(method, loop etc.) in which they are declared.
#y is an instance variable, they are visible anywhere in the instance of the class in which it has been defined.
You can access x if you explicitly provide it as local:
def show
render locals: {
x: 1
}
end
The recommended way to use variables in views is to use instance variables. That's because if you try to use a local variable and you didn’t pass a value in, you would get an error. But with instance variables, you would get a nil.
For more information on how to use local variables in a view, you can check the link.
As per the description and the answers mentioned above it is clear that instance variables are accessible in the views.
Answering the below mentioned point
Conceptually, why #y is accessible in the .html.erb view, but x is
not.
While rendering the views, instance variables and their values are taken from the controller and passed to the view initializer which assigns them to the view instance.
This is done using these ruby methods:
instance_variables - gets names of instance variables
instance_variable_get(variable_name) - gets value of an instance variable
instance_variable_set(variable_name, variable_value) - sets value of an instance variable
[https://github.com/rails/rails/blob/0c5552a3dd28e35cce64462765cc41c5355db0f1/actionpack/lib/abstract_controller/rendering.rb#L138-L145][1]
In the above link the method named
"view_assigns" -> collects the controller instance variable
"view_context passes" -> them to the views
"assign(new_assigns)" -> setting them in the view
As per your example, #y in the controller is not the same #y in the view, however at the very high level it seems like they're the same. Rails does a lot of magic under the hood, As you already know (if not), Rails believes in Convention over configuration, at this point Rails will look for all the instance variables in the controller and will copy them over to the views, even let's say you don't want them, it'll be there. Rails is exposing all the instance variables to the respective view.
So far, this has been my understanding, if I have missed something, please add more details.
About variables:
foo = 'bar' # this means that you declare a local variable, not accessible from view
#foo = 'bar' # means you declare an instance_variable, this will be available on view
Also you can define helper_method on controller that execute and returns some data, like helpers.

Ruby - Why is it possible to use Instance variables like everywhere

I'm into Ruby on Rails programming for almost 5 weeks now.
I was wondering why people always use instance variables instead of local ones.
I always thought that you would use instance variables only for classes (so these instance variables are the attributes of the class).
But people also use them not only for being attributes of a class. And this is the part where I am getting confused.
For instance, take a look at these lines of codes:
class Foo
def print_a_hello
puts "Hello World"
end
end
#instance_variable = Foo.new
#instance_variable.print_a_hello
# => "Hello World"
locale_variable = Foo.new
locale_variable.print_a_hello
# => "Hello World"
So, who of you got a great explanation for me?
I was wondering why people always use instance variables instead of locale ones.
I'm not sure how you get that impression. I certainly don't "always" use instance variables. I use instance variables when I need an instance variable, and I use local variables, when I need a local variable, and most code I see does it the same way.
Usually, it doesn't even make sense to interchange them. They have completely different purpose: local variables have static lexical scope, instance variables have dynamic object scope. There's pretty much no way to interchange them, except for the very narrow case of a simple single-file procedural script, where the dynamic scope of the top-level main object and the lexical scope of the script body are identical.
I always thought that you would use instance variables only for classes (so these instance variables are the attributes of the class).
No. Instance variables are attributes of the instance (i.e. object), not the class, that's why they are called "instance variables", after all. Class variables are attributes of the class, but class variables are a different beast and only used in very specific circumstances. (Classes are objects (i.e. instances), too, so they can have instance variables as well; there's generally no need to use class variables, which have some weird and un-intuitive properties, unless you specifically need those weird and un-intuitive properties).
For instance, take a look on this short codelines:
class Foo
def print_a_hello
puts "Hello World"
end
end
#instance_variable = Foo.new
#instance_variable.print_a_hello
# => "Hello World"
locale_variable = Foo.new
locale_variable.print_a_hello
# => "Hello World"
This is the case I mentioned above: in this specific case (and only in this case), the dynamic scope of the top-level main object and the static lexical scope of the script body are identical, so it doesn't matter whether you use a local variable of the script body or an instance variable of the main object.
However, if we make just a tiny change to that, by adding a second script and requireing it from the first, that condition will no longer hold, because we now have two separate script bodies and thus two separate script scopes, but still only one top-level object.
The idiomatic way in your example would definitely be to use a local variable, and nobody I know would do otherwise.
Best use case for instance variables is in Controller's when you want to pass parameter to the view.
Then you use something like
class TestController < ActionController::Base
def show
#usable_in_view = Test.first
not_usable_in_view = Test.first
end
end
In your view you can now use #usable_in_view, but cant use variable not_usable_in_view. Most people always use instance variable in controllers even if they do not need them in view, because they do not understand why they need instance variable
Instance variables are used so that they can be accessed in the view page.
Local variables are not accessible in the view. It has become the habit even I sometimes write instance variables though it is not required in the view.:-)
People probably get in the [bad] habit of using instance variables everywhere since it's common in Rails to use them to get information from the controller to the view.
In my own Ruby code I use instance variables only when I need to, local variables otherwise. That's the proper way to use Ruby.

Global variable that is accessible in models without passing any information from controller

I know how we can declare global variable in config file and then access through
Service Locator
Currently I am getting this Global variable in controller with the help of service locator and then pass it to models while creating object.
Question: Is it possible that I can get the Global variable in model directly rather than passing in all the models through controller?
Yes it is possible to get the variable declared in global file into model directly. Instead of declaring it as variable, just define it as constant in the global file so that you can access that variable easily in any models.
define('VAR_NAME',Value);
and access the variable using.
constant('VAR_NAME');
Hope it helps
Thanks

Rails: How can an instance variable declared in a controller accessible in a view?

Ruby instance variables are accessible to a single object. But in rails, if I declare an instance variable in a controller, it is still accessible in the views. What is the architecture behind this?
Well, your controller calls render which renders your templates. So, the template code is being run within the scope of the controller instance. Therefore, you can use any instance variables declared.

initializing a class with config (yaml), and setting a variable that should be a single instance

I am getting confused as to how to properly set variables in a initializer, I want these to be class level variables, not instance.
And I also want to then create a single instance of another object (it is a connection object, which already has connection pooling built in, so I just need a single reference to it).
My initializer /initializers/my_class.rb
yml = YAML.load_file("#{Rails.root}/config/my_class.yml")
MYMODULE::MyClass.init(yml)
And here is my my_class.rb:
module MYMODULE
class MyClass
def self.init(yml)
#post_url = yml["defaults"]["post_url"]
end
def self.post_url
#post_url
end
# this should be a single instance
def connection_pool
# ???
end
end
end
These class level variables, how can I access them from both class methods and instance methods?
I'm getting wierd behaviour, and I'm confused as to how to reference the post_url from inside of either class methods and instance methods.
I have seen the following ways, unsure which is correct:
self.class.post_url
MyClass.post_url
#post_url
post_url
self.post_url
self.class.post_url or MyClass.post_url will work. The difference is how they work for subclasses (in the former case, subclasses will use their own version of this variable automatically, in the latter, they would share the variable in MyClass).
There is no way to directly access class instance variables from an instance: you have to call a class method which returns (or sets) them. See also: cattr_accessor.
That said, if this is really a singleton, it seems a little strange to me that you would configure part of it on the class, and then reference that info in the (single) instance. Wouldn't it make more sense just to configure this stuff on the instance? Or use a module as a singleton and not create an instance at all?

Resources