Why Aren't Global (Dollar-Sign $) Variables Used

Why aren't global (dollar-sign $) variables used?

Is it because of design flaw issue ?

Design... flaw? That's a design blessing, design boon, design merit, everything but flaw! Global variables are bad, and they are especially bad in Web applications.

The sense of using global variables is keeping—and changing—the "global state". It works well in a simple single-threaded scripts (no, not well, it works awful, but, still, works), but in web apps it just does not. Most web applications run concurrent backends: i.e. several server instances that respond to requests through a common proxy and load balancer. If you change a global variable, it gets modified only in one of the server instances. Essentially, a dollar-sign variable is not global anymore when you're writing a web app with rails.

Global constant, however, still work, because they are constants, they do not change, and having several instances of them in different servers is OK, because they will always be equal there.

To store a mutable global state, you have to employ more sophisticated tools, such as databases (SQL and noSQL; ActiveRecord is a very nice way to access the DB, use it!), cache backends (memcached), even plain files (in rare cases they're useful)! But global variables simply don't work.

Is it good practies to use Global variable in ROR 3.0

Regardless of where global variables are used, they are generally bad.

Why Global Variables Should Be Avoided When Unnecessary

  • Non-locality -- Source code is easiest to understand when the scope of its individual elements are limited. Global variables can be read or modified by any part of the program, making it difficult to remember or reason about every possible use.
  • No Access Control or Constraint Checking -- A global variable can be get or set by any part of the program, and any rules regarding its use can be easily broken or forgotten. (In other words, get/set accessors are generally preferable over direct data access, and this is even more so for global data.) By extension, the lack of access control greatly hinders achieving security in situations where you may wish to run untrusted code (such as working with 3rd party plugins).
  • Implicit coupling -- A program with many global variables often has tight couplings between some of those variables, and couplings between variables and functions. Grouping coupled items into cohesive units usually leads to better programs.
  • Concurrency issues -- if globals can be accessed by multiple threads of execution, synchronization is necessary (and too-often neglected). When dynamically linking modules with globals, the composed system might not be thread-safe even if the two independent modules tested in dozens of different contexts were safe.
  • Namespace pollution -- Global names are available everywhere. You may unknowingly end up using a global when you think you are using a local (by misspelling or forgetting to declare the local) or vice versa. Also, if you ever have to link together modules that have the same global variable names, if you are lucky, you will get linking errors. If you are unlucky, the linker will simply treat all uses of the same name as the same object.
  • Memory allocation issues -- Some environments have memory allocation schemes that make allocation of globals tricky. This is especially true in languages where "constructors" have side-effects other than allocation (because, in that case, you can express unsafe situations where two globals mutually depend on one another). Also, when dynamically linking modules, it can be unclear whether different libraries have their own instances of globals or whether the globals are shared.
  • Testing and Confinement - source that utilizes globals is somewhat more difficult to test because one cannot readily set up a 'clean' environment between runs. More generally, source that utilizes global services of any sort (e.g. reading and writing files or databases) that aren't explicitly provided to that source is difficult to test for the same reason. For communicating systems, the ability to test system invariants may require running more than one 'copy' of a system simultaneously, which is greatly hindered by any use of shared services - including global memory - that are not provided for sharing as part of the test.

Global vs local variables?

Everything inside of a method definition cannot see local variables from other places. That sounds weird, but here's two ways to fix it:

    result = 1
number = 10

def factorial(num,result_value)
while (num > 1)
result_value = result_value.to_i * num
num -= 1
end
puts result_value
end

factorial(number, result)

That passes result as an argument. That's a great way of handling the method because it doesn't allow you to change the value of result from within the method. That might not seem like a big deal but "pure methods" like this become very valuable as the size the code increases.

This is the "dirty" or un-pure way of doing the same thing:

@result = 1

def factorial(num)
while (num > 1)
@result = @result.to_i * num
num -= 1
end
puts @result
end

Putting an @ in front of a variable name allows its scope to expand to methods defined outside of its scope. This becomes a problem as the complexity of your code increases.

Random personal opinion: even though Ruby doesn't require you to put the parentheses next to a method definition, you always should. It makes the code a lot more explicit and easier to read. Follow your heart though ;)

How to shorten binding.pry without using dollar-sign global variable?

So, after a little thought, here's the solution. It will require one more next to hit. But there are the other benefits - you can define it per environment, so you'll never get an error on production if you forget to delete or comment out bp.

Go to initializers, and create pry.rb file with these contents:

def bp
unless %w(production).include? Rails.env
binding.pry
end
end

Have fun!

How to setup dynamic variables before request?

You don't need to handle it before the request. You have two types of urls: blogcrea.com/[blogname]/[other params] and [customdomain]/[other params]

The best way to handle this is with two sets of routes depending on the domain:

constrains(CheckIfBlogCrea) do
match '/:blog(/:controller(/:action(/:id)))' # Build your routes with the :blog param
end

match '/(:controller(/:action(/:id)))' # Catch the custom domain routes

Matcher for common domain:

module CheckIfBlogCrea

def self.matches?(request)
request.host == 'blogcrea.com'
end

end

Now you know the routes will always match. Ofcourse you still have to know which blog to show. This can easily be done in the ApplicationController with a before_filter

class ApplicationController < ActionController::Base

before_filter :load_blog

protected

def load_blog
# Custom domain?
if params[:blog].nil?
@blog = Blog.find_by_domain(request.host)
else
@blog = Blog.find_by_slug(params[:blog])
end
# I recommend to handle the case of no blog found here
end

end

Now in your actions you'll have the @blog object that tells you which blog it is, it's also available in the views when rendering.

Why aren't more of my controllers failing due to skip_forgery_protection not being used?

I'm not sure I understand your question correctly.

But, if you are asking why forgery_protection only applies to POST, PUT, PATCH, and DELETE then the doc says,

Turn on request forgery protection. Bear in mind that GET and HEAD requests are not checked.

And from wikipedia,

In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered "safe". This allows user agents to represent other methods, such as POST, PUT and DELETE, in a special way, so that the user is made aware of the fact that a possibly unsafe action is being requested.

Because of this assumption, many existing CSRF prevention mechanisms in web frameworks will not cover GET requests, but rather apply the protection only to HTTP methods that are intended to be state-changing.

What is the purpose of the dollar sign in JavaScript?

A '$' in a variable means nothing special to the interpreter, much like an underscore.

From what I've seen, many people using jQuery (which is what your example code looks like to me) tend to prefix variables that contain a jQuery object with a $ so that they are easily identified and not mixed up with, say, integers.

The dollar sign function $() in jQuery is a library function that is frequently used, so a short name is desirable.



Related Topics



Leave a reply



Submit