Ruby on Rails- :symbols, #iVars and "strings" - oh my! - ruby-on-rails

New to Rails and trying to get my head around when/why to use :symbols, #ivars , "strings" within the framework.
I think I understand the differences between them conceptually
only one :symbol instance per project
one #ivar per instance
multiple "strings" - as they are created whenever referenced (?)
Feel free to correct me!
The main confusion comes from understanding the rules & conventions of what Rails expects - where and WHY?
I'm sure there's an "Ah ha!" moment coming but I haven't had it yet...as it seems pretty arbitrary to me (coming from C/Obj-C).
-thx

The #instance_variable is an instance variable. It is usually defined in the controller and accessible in the views.
The "string" is a string, like as in any other language.
The :symbol, is as you mentioned it's an efficient way of representing names and strings; they are literal values. It is initialized and exists only once during the ruby session. It's not a string, since you don't have access to String methods; it's a Symbol. On top of that, it's immutable. For those reasons, it becomes very handy in representing keys in hashs. Rails methods uses hashes, thus, you find symbols a bit everywhere in Rails.

Instance variables are pretty straightforward: they track properties/values of a particular instance, so you use them when you the values will vary across instances.
Symbols vs. strings are a bit more arbitrary. Symbols are generally used for constant values, in much the same way that a language such as C would use enums; Ruby doesn't have enums, so symbols are often used to fill that gap. Strings are used for more varied pieces of text that won't be used as a flag or similar constant.

Symbols are kind of like pointers (not in the C-ish way, but in C-ish thinking, they point). Well, you use symbols when you are manipulating properties. They are one of the great benefits of dynamic typing if you'd ask me. (For potential voters I do not mean any harm, I do know that they are not pointers, but it felt 'ah-ha!' for me).
:action => "index"
Instance variables are needed when you fetch data from your model and you want to use them across your views (inside your controller method).
def my_controller_method
#myposts = Post.find(:all)
end
# inside view
<% for #myposts do |m| %>
<i><%= m.title %></i>
<% end %>
Just a heads up, the rules and conventions kinda change rapidly (as I discovered on my Rails journey) quite a lot per version. Having the right guide with the right Rails helps. Good luck with coding!

Instance variables don't really belong in the same list as strings and symbols. Strings and Symbols are types of classes whereas instance variables are a type of variable. So instance variables (#var) are just a way to store a value between methods of one instance of one class:
class Calculator
#counter = 0
def inc
#counter += 1
end
def dec
#counter -= 1
end
end
Here is a good article on the distinction between symbols and strings.

The Rails controller access the rails database through Models by ORM (Object Relation Mapping)i.e Model class will mapped to its corresponding table and Objects are directly mapped to rows in the table.In order to get the results for a given user query,the instance variable (#instance_variable) is the perfect choice to deal with it.

Related

Is there a way to directly access and/or manipulate the `locals` hash from inside of a `partial` Rails ERB template?

I am currently splitting some code out to make it more reusable, and other code more succinct.
I realize I am passing a good bit of options into the locals hash, besides just the form variable, and all of these seem to only apply directly to the input object I am creating.
I was thinking of merging the locals hash into another that contains some defaults, and passing that to the input creation function.
After some researching API docs like these:
Ruby on Rails - API - ActionView::Renderer
Ruby on Rails - API - ActionView::PartialRenderer
and digging around to find these last 2 methods in the stack trace:
From: .../.rvm/gems/ruby-2.1.5#ux-rails3.2/gems/actionpack-3.2.22.5/lib/action_view/template.rb # line 145 ActionView::Template#render_without_mini_profiler: ... 2.1.5 (#<ActionView::Template:0x007fa41e138cc8>):0 >
From: .../app/views/shared/_checkbox_group.html.erb # line 3 ActionView::CompiledTemplates#_app_views_shared__checkbox_group_html_erb___4197967411385159258_70171427980900: ... 2.1.5 (#<#<Class:0x007fa40f30fec0>:0x007fa40fe71c50>):0 >
RVM, Ruby, Rails, Formtastic, Pry, Byebug, & Pry-Byebug.
Old, not-so-helpful workaround answer
As it may be convenient from the question's phrasing, one method is to not spend time diving into the Rails template rendering framework code and documentaion, and instead simply provide the options I mentioned for the locals hash, inside of a single property containing a new hash containing them, and pass that into the template.
Later I use that hash to merge with the default hash I had inside of the template and pass that to the input function as normal.
I could leave the Q&A here in case there might still me reasons people would want to directly access the locals hash, or could even develop an alternative approach that would be possible as well.
Update
So I dove into the Rail template rendering framework...
Exposition
I started simply taking this:
2.1.5 (#<#<Class:0x007fc01d352e08>:0x007fc018879698>):0 > self.class
=> #<Class:0x007fc01d352e08>
That wasn't much helpful, then went up into actionpack-3.2.22.5/lib/action_view/template.rb:145 to find this:
2.1.5 (#<ActionView::Template:0x007fc011e90510>):0 > method_name
=> "_app_views_shared__adrad_index_html_erb___3381877171036202789_70231455466120"
2.1.5 (#<ActionView::Template:0x007fc011e90510>):0 > view.method(method_name.to_sym)
=> #<Method: #<Class:0x007fc01d352e08>(ActionView::CompiledTemplates)#_app_views_shared__adrad_index_html_erb___3381877171036202789_70231455466120>
2.1.5 (#<ActionView::Template:0x007fc011e90510>):0 > view.method(method_name.to_sym).source_location
=> ["<our project_path>/app/views/shared/some.html.erb", 0]
Where the last point wasn't great, but then I started looking for ActionView::CompiledTemplates, which unfortunately, you cannot use source_location to find, or instance variable declarations for that matter (different issue :) ).
I decided to randomly search the actionpack-.../lib/action_view/ directory to find a reference or so in context.rb, but instead of looking inside of template.rb, I skipped straight to searching for locals in that gem's files now.
resolver.rb did not help much, and neither did template_renderer.rb.
Once I delved into template.rb and found the familiar above stack frame for render that my answer had to be between that and my actual page with the included locals properties,
I followed compile! to its definition,
saw a familiar ActionView::CompiledTemplates,
then a compile,
found an interesting arbitrary, literal, meta source manipulation, as I was sort of expecting with the lack of more stack frames in-between to scour, and the callback-esque naming scheme, I found this curious variable, as a parameter to the dynamically-generated template function: local_assigns.
I quickly jump around to locals_code's definition since it is also used and verify this is source variable enumeration I was looking for!
Answer
local_assigns!
Also, I currently don't believe the hash provides any properties I would want to avoid, such as any information specific to only the current partial template page that I wouldn't want to be propagated to the child partial template page.
Update
I am starting to do more with this variable, and I wonder if I am limited.
I want to mix-in some default values, which might involve using binding.local_variable_set, but it is not able to create new local variables (How to dynamically create a local variable?), so I might just have to use my own nested data structure now..

Rails Limit Model To 1 Record

I am trying to create a section in my app where a user can update certain site wide attributes. An example is a sales tax percent. Even though this amount is relatively constant, it does change every few years.
Currently I have created a Globals model with attributes I want to keep track of. For example, to access these attributes where needed, I could simply do something like the following snippet.
(1+ Globals.first.sales_tax) * #item.total
What is the best way to handle variables that do not change often, and are applied site wide? If I use this method is there a way to limit the model to one record? A final but more sobering question.......Am I even on the right track?
Ok, so I've dealt with this before, as a design pattern, it is not the ideal way to do things IMO, but it can sometimes be the only way, especially if you don't have direct disk write access, as you would if deployed on Heroku. Here is the solution.
class Global < ActiveRecord::Base
validate :only_one
private
def only_one
if Global.count >= 1
errors.add :base, 'There can only be one global setting/your message here'
end
end
end
If you DO have direct disk access, you can create a YAML config file that you can read/write/dump to when a user edits a config variable.
For example, you could have a yaml file in config/locales/globals.yml
When you wanted to edit it, you could write
filepath = "#{Rails.root}/config/locales/globals.yml"
globals = YAML.load(File.read("#{Rails.root}/config/locales/globals.yml"))
globals.merge!({ sales_tax: 0.07 })
File.write(filepath) do |f|
f.write YAML.dump(globals)
end
More on the ruby yaml documentation
You could also use JSON, XML, or whatever markup language you want
It seems to me like you are pretty close, but depending on the data structure you end up with, I would change it to
(1+ Globals.last.sales_tax) * #item.total
and then build some type of interface that either:
Allows a user to create a new Globals object (perhaps duplicating the existing one) - the use case here being that there is some archive of when these things changed, although you could argue that this should really be a warehousing function (I'm not sure of the scope of your project).
Allows a user to update the existing Globals object using something like paper_trail to track the changes (in which case you might want validations like those presented by #Brian Wheeler).
Alternatively, you could pivot the Global object and instead use something like a kind or type column to delineate different values so that you would have:
(1+ Globals.where(kind: 'Colorado Sales Tax').last) * #item.total
and still build interfaces similar to the ones described above.
You can create a create a class and dump all your constants in it.
For instance:
class Global
#sales_tax = 0.9
def sales_tax
#sales_tax
end
end
and access it like:
Global.sales_tax
Or, you can define global variables something on the lines of this post

Iterating through array of Models in rails

Yet another ruby question but this is a bunch of questions in one. I'm really starting to like rails but there are some questions that I'd just like to ask straight out.
Right now, I'm implementing a queue in sqlite. I already have a scaffold setup with this working OK. The purpose is for a web crawler to read through the array and determine which links he should crawl next.
The architecture in the program is 2 controllers. one for Job and one for crawler. The Jobs has the standard Crud interface supplied by scaffold. Where I'm falling down is I'm still trying to understand how these things communicate with eachother.
The Job is formatted as a url:string and depth:decimal. The table is already populated with about 4 objects.
#sitesToCrawl = Job.all
#sitesToCrawl.each {|x|puts Job.url}
I have a bunch of questions about the above.
At the moment, this was supposed to display all the jobs and I foolishly thought it would display plain text but its actually a hexidecimal pointer to the object itself. What Im trying to do is iterate through the #sitesToCrawl and put out each Jobs url.
Questions start here:
1: I know ruby is dynamically typed. Will #sitesToCrawl become an array like i want it to be with each slot containing a job.
2: #sitesToCrawl.each is pretty straighforward and I'm assuming its an iterator.
is X the name od the method or what is the purpose of the symbol or string between |*|
3: Puts and print are more or less the same yes? if i say #x = puts 3 then would x be 3?
4: Job.url. Can objects be referenced this way or should I be using
##sitesToCrawl = db.execute("SELECT url FROM jobs;")
where db is a new database
As Rubish Gupta pointed out, in your block, you should do x.url, otherwise you're trying to access the url method on the class Job, not on instances of Job. In other words, in blocks, the items in the pipes are the arguments of the block, and each will iterate through your array, passing in one item at a time to your block. Check out the doc here.
Just to extend this idea, each on Hashes (associative arrays, maps, whatever you know them as) will pass two variables to your block: a key and a value, like this:
a_hash.each {|key_var, val_var| puts "#{key_var} is associated with #{val_var}"}
Also, it's been a bit since I've done plain ActiveRecord models, but you might look into doing
#sitesToCrawl = Job.all.to_a
since Job.all is a lazy finder in that it's building a query in potentia: you've essentially built a query string saying SELECT * FROM jobs, but it might not be executed until you try to access the items. each might do that, I can't remember off the top of my head, but if you're using a debugger to look at it, I know you need to_a to get it to run the query.
You should absolutely be using job_instance.url - that's the beauty of ActiveRecord, it makes database access easy, provided everything gets set up right :)
Finally, puts and print are almost the same - the difference is that puts "string" is essentialy print "sting"; STDOUT.flush - it flushes at the end of the statement.

Should Rails helpers assume an instance variable exists or should they receive them as parameters?

I'm wondering if there's a specific programming principle (Demeter?) that supports the idea that Rails helpers should never use controller instance variables, rather, they should receive such variables as function parameters. For example, assume my ChickensController#squawk action creates an instance variable called #egg. Furthermore, assume the squawk view contains a call to a helper called cockadoodledoo, implemented like so:
def cockadoodledoo
#egg.to_s
end
Would it be better or unnecessarily verbose to pass #egg as a parameter, such that the view calls cockadoodledoo(#egg) and for the helper to resemble:
def cockadoodledoo(egg)
egg.to_s
end
I hope one of you happy hackers is bored enough on a Friday afternoon to assert an answer. Cockadoodledoo!
This question here is similar, but was never accurately answered.
Receive them as a param. Otherwise, as the app grows, it gets very difficult to trace where the instance vars are being set when refactoring, troubleshooting, etc.
Also, I believe there's a general best practice to only use instance vars in views within the initial template...and from there you should pass the var into helpers and other partials.
I'd say you should always pass the variables explicitly to your helper for 2 reasons:
you control exactly what you do
above all, you can test your helper
I don't know if there is any named principle governing this sort of thing but I would pass an argument. Not only will the argument make your helper easier to test and your application's data flow easier to follow but it will also let you use one helper for a single instance as well as a list; if you pass an argument then both:
<%= cockadoodledoo #egg %>
and:
<% #eggs.each do |egg| %>
<%= cockadoodledoo egg %>
<% end %>
will work as expected without introducing a special cockadoodledoo that handles a list in #eggs rather than a single #egg.
Since helper messages are mixed in to all controllers, hence available to all views (including partials and layouts), it's always wise to establish a clear contract - the parameters.
The only exception I could think of is when a instance variable is also available to all views and controllers, like a menu or something similar.

When you say Ruby is reflective, does this mainly refer to "duck typing"?

I was reading a text describing Ruby and it said the following:
Ruby is considered a “reflective”
language because it’s possible for a
Ruby program to analyze itself (in
terms of its make-up), make
adjustments to the way it works, and
even overwrite its own code with other
code.
I'm confused by this term 'reflective' - is this mainly talking about the way Ruby can look at a variable and figure out whether it's an Integer or a String (duck typing), e.g.:
x = 3
x = "three" # Ruby reassigns x to a String type
To say Ruby is "reflective" means that you can, for instance, find out at runtime what methods a class has:
>> Array.methods
=> ["inspect", "private_class_method", "const_missing",
[ ... and many more ... ]
(You can do the same thing with an object of the class.)
Or you can find out what class a given object is...
>> arr = Array.new
=> []
>> arr.class
=> Array
And find out what it is within the class hierarchy...
>> arr.kind_of?
>> arr.kind_of? Array
=> true
>> arr.kind_of? String
=> false
In the quote where they say "it’s possible for a Ruby program to analyze itself" that's what they're talking about.
Other languages such as Java do that too, but with Ruby it's easier, more convenient, and more of an everyday part of using the language. Hence, Ruby is "reflective."
No, it means that you can issue a ruby command to get information about, well, just about anything. For example, you can type the command File.methods() to get a listing of all methods belonging to the File module. You can do similar things with classes and objects -- listing methods, variables, etc.
Class reopening is a good example of this. Here's a simple example:
class Integer
def moxy
if self.zero?
self - 2
elsif self.nonzero?
self + 2
end
end
end
puts 10.moxy
By reopening a standard Ruby class - Integer - and defining a new method within it called 'moxy', we can perform a newly defined operation directly on a number. In this case, I've defined this made up 'moxy' method to subtract 2 from the Integer if it's zero and add two if it's nonzero. This makes the moxy method available to all objects of class Integer in Ruby. (Here we use the 'self' keyword to get the content of the integer object).
As you can see, it's a very powerful feature of Ruby.
EDIT: Some commenters have questioned whether this is really reflection. In the English language the word reflection refers to looking in on your own thoughts. And that's certainly an important aspect of reflection in programming also - using Ruby methods like is_a, kind_of, instance_of to perform runtime self-inspection. But reflection also refers to the the ability of a program to modify its own behavior at runtime. Reopening classes is one of the key examples of this. It's also called monkey patching. It's not without its risks but all I am doing is describing it here in the context of reflection, of which it is an example.
It refers mainly at how easy is to inspect and modify internal representations during run-time in Ruby programs, such as classes, constants, methods and so on.
Most modern languages offer some kind of reflective capabilities (even statically typed ones such as Java), but in Ruby, it is so easy and natural to use these capabilities, that it really make a real difference when you need them.
It just makes meta-programming, for example, an almost trivial task, which is not true at all in other languages, even dynamic ones.

Resources