Condition in ruby on rails - if else - ruby-on-rails

I'm not really sure what this means. This is from Ruby on Rails in controller class and been trying to figure out what the below code do.
payload = if params.key? :data
//do something
else
//else do something
end
This is in the controller class. What does the params.key? :data do?
The data variable doesn't exist in the whole class but just in this block.

:data is not a variable but a symbol.
.key? is a method and in ruby you do not need parentheses to pass a parameter such as :data.
So this bit of code asks if params has the symbol :data as a key (in a map) and uses the returning boolean for the conditional.

In this snippet data is not a variable, it is a symbol literal. Java doesn't have a direct counterpart of Ruby's symbols AFAIR, but you can think of it as of some immutable identifier (kinda "immutable string with some additional cool properties that don't matter in the context we discuss here").
Next, params represents query params and is provided by the underlying middleware. It is a Hash-like data structure where Hash is a Ruby's counterpart of Java's HashMap that maps keys to values.
Next, params.key? :data is the same as params.key?(:data) - parentheses around method's arguments are optional in Ruby in most cases, and people tend to abuse this controversial feature. It just checks if params hash(map) contains a :data key (see Hash#key?).
And finally since everything in Ruby is an expression, if... else... end has a meaningful return value (the result of the particular branch execution) that is further assigned to the payload.

Related

Is there a way to overwrite the `{ }` object?

I'm trying to make all Hashes in my program be ActiveSupport::OrderedHash.
I can override the Hash.new constructor by ::Hash = ActiveSupport::OrderedHash but {}.class is still hash.
def {} gives me a syntax error.
It was recommended that this is a duplicate of this question, but I don't think that is the case. My question isn't about subclassing Hash, it's about overwriting the default { } => Hash constructor.
Hash literal {} is hard-coded in Ruby, and you cannot change it. {} will become a Hash. However, since Ruby's class can be modified, you can remove all unnecessary methods, constants, variables from Hash, and copy everything that is in ActiveSupport::OrderedHash into Hash.
There are only very few languages which allow you to overload literals (I only know of two: Ioke and Seph). Ruby is not one of them.
See also overloading Ruby's […] Array creation shorthand, Which method is invoked by […] in Ruby?, and How to intercept the call to constructor of class Hash?.

Rails params "method" isn't a method, is it?

In the Rails documentation, the following example is given as a way to display what the server receives from a POST request:
def create
render plain: params[:article].inspect
end
In the subsequent description, the text states
The params method is the object which represents the parameters (or fields) coming in from the form. The params method returns an ActiveSupport::HashWithIndifferentAccess object.
While I understand that all methods are objects, I don't understand how it's correct to refer to the params object as a method. Specifically, the phrase "returns an ActiveSupport::HashWithIndifferentAccess object" suggests to me that there are two calls going on--what in python might look like:
params().__getitem__('article')
but I don't think that's what's actually going on.
The conversation around those lines also refers to params as a method, so I'm starting to think I must be missing something.
I'm new to Ruby, and while I understand that all methods are objects,
No, they aren't. Methods belong to objects (more precisely: methods are defined in modules, and executed in the context of objects), but they are not, by themselves, objects. (It is, however, possible to obtain a reflective proxy which represents the concept of a method by calling the method method, which returns a Method object.)
I don't understand how it's correct to refer to the params object as a method.
Because it is a method. Not an object.
What else would it be? Syntactically, it's obvious that it can only be one of three things: a keyword, a variable, or a method call.
It can't be a keyword, because Rails is just a Ruby library, and Ruby libraries can't change the syntax of the language (e.g. add or remove keywords). It can't be a variable, because in order for it to be parsed as a variable, the parser would need to have seen an assignment to it within the same block.
Ergo, the only thing it can possibly be, is a method call. You don't even need to know anything about Rails to know this. It's just basic Ruby syntax 101.
Specifically, the phrase "returns an ActiveSupport::HashWithIndifferentAccess object" suggests to me that there are two calls going on--what in python might look like:
params().__getitem__('article')
but I don't think that's what's actually going on.
That is exactly what is going on. You call the method params and then you call the method [] on the object that is returned by calling the method params.
This is in no way different from foo.bar: you call foo, then call bar on the return value of foo.
The params method is a method, returns a hash (which holds some details about parameters send to the app). Simplified it looks like this:
def fake_params
{ :controller => 'foo', :action => 'bar' }
end
You can call another method directly on the returned hash like this:
fake_params[:action] #=> 'bar'
params is a method defined in ActionController::Metal which returns the request.parameters object.
https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal.rb#L140

attr_accessor strongly typed Ruby on Rails

Just wondering if anyone can shed some light on the basics of getter setters in Ruby on Rails with a view on strongly typed. I am very new to ruby on rails and predominately have a good understanding of .NET.
For example, let's consider we have a .net class called Person
class Person
{
public string Firstname{get;set;}
public string Lastname{get;set;}
public Address HomeAddress{get;set;}
}
class Address
{
public string AddressLine1{get;set;}
public string City{get;set;}
public string Country{get;set;}
}
In Ruby, I would write this as
class Person
attr_accessor :FirstName
attr_accessor :LastName
attr_accessor :HomeAddress
end
class Address
attr_accessor :AddressLine1
attr_accessor :City
attr_accessor :Country
end
Looking at the Ruby version of the Person class how do I specify the types for the accessor methods FirstName, LastName and HomeAddress? If I were to consume this class I could feed any type into HomeAddress but I want this accessor method to accept only the TYPE Address.
Any suggestions?
TL;DR: No it's not possible ... and long answer, yes it is possible, read the metaprogramming section :)
Ruby is a dynamic language, that's why you won't get compile time type warnings/errors as you get in languages like C#.
Same as you can't specify a type for a variable, you can't specify a type for attr_accessor.
This might sound stupid to you coming from .NET, but in the Ruby community, people kind of expect you to write tests. If you do so, these types of problems will basically vanish. In Ruby on Rails, you should test your models. If you do so, you won't really have any trouble with accidentaly assigning something somewhere wrong.
If you're talking about ActiveRecord in Ruby on Rails specifically, assigning a String into an attribute which is defined as an Integer in the database will result in exception being thrown.
By the way, according to convention, you shouldn't use CamelCase for attributes, so the correct class definition should be
class Person
attr_accessor :first_name
attr_accessor :last_name
attr_accessor :home_address
end
class Address
attr_accessor :address_line1
attr_accessor :city
attr_accessor :country
end
One reason for this is that if you Capitalize the first letter, Ruby will define a constant instead of a variable.
number = 1 # regular variable
Pi = 3.14159 # constant ... changing will result in a warning, not an error
Metaprogramming hacks
By the way, Ruby also has insanely huge metaprogramming capabilities. You could write your own attr_accessor with a type check, that could be used something like
typesafe_accessor :price, Integer
with definition something like
class Foo
# 'static', or better said 'class' method ...
def self.typesafe_accessor(name, type)
# here we dynamically define accessor methods
define_method(name) do
# unfortunately you have to add the # here, so string interpolation comes to help
instance_variable_get("##{name}")
end
define_method("#{name}=") do |value|
# simply check a type and raise an exception if it's not what we want
# since this type of Ruby block is a closure, we don't have to store the
# 'type' variable, it will 'remember' it's value
if value.is_a? type
instance_variable_set("##{name}", value)
else
raise ArgumentError.new("Invalid Type")
end
end
end
# Yes we're actually calling a method here, because class definitions
# aren't different from a 'running' code. The only difference is that
# the code inside a class definition is executed in the context of the class object,
# which means if we were to call 'self' here, it would return Foo
typesafe_accessor :foo, Integer
end
f = Foo.new
f.foo = 1
f.foo = "bar" # KaboOoOoOoM an exception thrown here!
or at least something along these lines :) This code works! Ruby allows you to define methods on the fly, which is how attr_accessor works.
Also blocks are almost always closures, which means I can do the if value.is_a? type without passing it as a parameter.
It's too complicated to explain here when this is true and when it's not. In short, there are different types of blocks
Proc, which is created by Proc.new
lambda, which is created by the keyword lambda
one of the differences is that calling return in a lambda will only return from the lambda itself, but when you do the same thing from a Proc, the whole method around the block will return, which is used when iterating, e.g.
def find(array, something)
array.each do |item|
# return will return from the whole 'find()' function
# we're also comparing 'item' to 'something', because the block passed
# to the each method is also a closure
return item if item == something
end
return nil # not necessary, but makes it more readable for explanation purposes
end
If you're into this kind of stuff, I recommend you check out PragProg Ruby Metaprogramming screencast.
Ruby is a dynamically typed language; like many dynamically typed languages, it adheres to duck typing -- from the English Idiom, "If it walks like a duck and quacks like a duck, then it's a duck."
The upside is that you don't have to declare types on any of your variables or class members. The restrictions on what types of objects you can store into the variables or class members comes only from how you use them -- if you use << to "write output", then you could use a file or array or string to store the output. This can greatly increase the flexibility of your classes. (How many times have you been upset that an API you must use required a FILE * C standard IO file pointer rather than allowing you to pass in a buffer?)
The downside (and, in my mind, it's a big one) is that there's no easy way for you to determine what data types you can safely store into any given variable or member. Perhaps once every leap year, a new method is called on a variable or member -- your program might crash with a NoMethodError, and your testing might have missed it completely because it relied on inputs you might not realize were vital. (This is a fairly contrived example. But corner cases are where most programming flaws exist and dynamic typing makes corner cases that much harder to discover.)
In short: there's no restriction on what you can store in your Address fields. If it supports the methods you call on those objects, it is -- as far as the language is concerned -- an Address. If it doesn't support the methods you need, then it will crash during sufficiently-exhaustive testing.
Just be sure to use the testing facilities to their fullest, to make sure you're exercising your code sufficiently to find any objects not fully compliant with a required API.

I don't get the idea behind Ruby Proc... why not just use normal Method?

I guess the title says it. I'm reading a book and I can see how they work but why would I create them instead of normal methods with normal parameters?
I searched Google and SO I just got confused more.
Please clarify. Thanks.
A proc is different because you can store it in a variable. Therefore you can pass it as a paramater to a function, return it from a function, manipulate it, etc.
Procs, lambdas and blocks are one of the main things that make Ruby awesome.They are at the heart of Ruby's iterators for example. When you do something like:
collection.each do |item|
//process item
end
you are basically passing a block (a Proc object) to the each function.
Let's say you a bunch of arrays, that you want to process in the same way. To save you from writing the each code every single time you can do something like:
handler = Proc.new{|item| do_something_with(item)}
array1.each &handler
array2.each &handler
....
arrayn.each &handler
When you want to pass a Proc to a function as a block, you have to preceed it with an &. The same goes for when you define a function that accepts a block parameter.
Another useful way to use Proc, is in functions.
Say you have a function that instantiates an object, does some minor changes, and returns it. To make it more flexible, you can make it accept a block like so:
def new_item(param1, param2, &block)
my_item = Item.new
my_item.attribute1 = param1
my_item.attribute2 = param2
yield my_item if block_given?\
return my_item
end
Yield is where the magic happens. When that line is evaluated, the function will execute the block that you give it with my_item as a parameter. So you can do stuff like:
my_new_item = new_item(p1, p2) do |item|
item.attribute3 = some_value
end
Now, my_new_item will have its attribute3 set as well as any other modification than you do in the block.
You don't use Procs and lambdas to replace functions, you use them to augment functions.
You can have a function that returns a Proc that was built based on whatever parameters you give it. There are a lot of ways to be creative with Procs.
Procs can be passed around as objects and called when required. This is useful for modularity (amongst other things) and delayed processing. An example is the way ActiveRecord allows Procs in validations. Some examples:
validates_presence_of :admin_password, :if => Proc.new{|u| u.admin?}
In this case, the Proc is called (and reused) whenever the validation is carried out.
Procs - is just 'methods' with delayed call. You can save some code in proc and then execute it later. It is hard to explain where you can use them I'll try to get example from my projects.
A method is something concrete that you have to know how to invoke. Procs and blocks are arbitrary units of code that can be passed around and used at-will. You can think of a Proc as a sort of closure, I guess.
You use a Proc when your method needs help from whatever code is stored in the Proc. Maybe some logic to load a resource from somewhere, or something else non-trivial. Unlike a block, Procs are intended to be kept around, in a variable.
Good question, after answering on this question you will clearly know where and how to use Proc.
For my understanding, the advantage of Proc is that you can pass the Proc as parameter to another methods. When you're defining the usual method, it bound to current context and can't be changed, you can't pass this method to another places. But with Proc you can do this. All iterators use this magic. You just saying what to do with every item in the array (you've created the proc object) and passing to iterator, and then iterator takes this method as an object and execute deep inside in his functionality.
Another common use is to simplify things that are structured as interpreters. Suppose you have a calculator of some sort, you could do it like this (which separates the association between the operator and its definition):
def add(a, b); a + b; end
def sub(a, b); a - b; end
#...
if(op == '+')
add(a, b)
elsif(op == '-')
sub(a, b)
#...
else
raise 'Unknown operator'
end
Or you could use lambdas to make it a lot cleaner and tighter (i.e. pull the operator and its definition together to make it obvious what is going on):
ops = {
'+' => lambda { |a, b| a + b },
'-' => lambda { |a, b| a - b },
#...
}
raise 'Unknown operator' if(!ops.has_key?(op))
ops[op].call(a, b)
The latter approach also makes special cases stand out more (IMHO).
A surprising number of things can be structured as interpreters of custom data structures once you're used to this sort of approach.

Ruby Integer(), Array(), et al -- what are they? Where do they come from?

I've come across conversions of the form Array(value), String(value), and Integer(value) on occasion. It appears to me that these are just syntactic sugar for a call to the corresponding value.to_a, value.to_s, or value.to_i methods.
So I'm wondering:
Where/how are these are defined? I can't find them in Object, Module, Class, etc
Are there any common scenarios for which it's preferable to use these rather than the corresponding/underlying to_X method?
Could these be used in type-generic coercion? That is, can I do something along the lines of
[Integer, String, Array].each {|klass| klass.do_generic_coercion(foo) }
? (...and no, I don't really want to do that; I know the type I want out, but I'm looking to avoid the case statement.)
This is a good and difficult question. Let's answer the three parts.
First part
To find the definition, it is important to realize that the name of the method is "Array", etc., which can be quite counterintuitive, since methods are usually lowercase...
irb> method(:Array)
=> #<Method: Object(Kernel)#Array>
This tells you these are defined in Kernel, and thus available everywhere without requiring an explicit prefix.
Second part
Array(), String(),... are conversion methods. Calling obj.to_a will return an array, but will raise an NoMethodError if obj doesn't respond_to? :to_a. So the typical case when you'd prefer using Array(), String(), instead of to_a or to_s is when you are not positive an object responds to a given conversion method.
String(obj) will return nil if obj doesn't respond_to? :to_s. String(obj) will also check that the result of to_s is actually a string; it should be, but maybe an overly creative programmer decided to return something else?
Most other conversion methods act the same way, but Array(obj) is different. It will return [obj] if obj doesn't respond_to? :to_a. It will actually call to_ary (which is the implicit conversion operation, while to_a is the explicit one).
There is another important way to convert objects in 1.9 (and upcoming 1.8.8): Array.try_convert(obj). This returns nil if the obj does not respond_to? :to_ary. It will not call the to_a. Although they are longer to type, you might prefer using them when writing very general code that might accept different types of objects and want to avoid converting a hash to an array by mistake, for example (since Hash has a to_a method but not to_ary). When your method requires an array-like object and you are willing to do an explicit conversion, then obj.to_a is fine. The typical use of Array(obj) would be in a method that accepts either a single obj to act on, or a list of objects (although typically this is written as [*obj]).
Last part
Hopefully, the answers to the first two parts give you your final answer...
You can use:
[Integer, String, Array].each {|klass| klass.try_convert(foo) }
or
[:Integer, :String, :Array].each{|method| send(method, obj)}
Good question! Let's see if we can figure it out.
Ross-Harveys-MacBook-Pro:ruby-1.9.1-p376 ross$ irb
irb(main):001:0> Object.ancestors
=> [Object, Kernel]
irb(main):002:0> Kernel.ancestors
=> [Kernel]
irb(main):003:0> Kernel.class
=> Module
irb(main):004:0> Kernel.public_methods.include? "Array"
=> true
So, it looks like these are methods in the Kernel module that are mixed in to Object, so they are available without specifying a receiver. We might also want to peek at the C implementation, in object.c:
VALUE
rb_Array(VALUE val)
{
VALUE tmp = rb_check_array_type(val);
if (NIL_P(tmp)) {
tmp = rb_check_convert_type(val, T_ARRAY, "Array", "to_a");
if (NIL_P(tmp)) {
return rb_ary_new3(1, val);
}
}
return tmp;
}
One thing seems easy to conclude, the default .to_a is deprecated, so it does seem like Array(x) is the canonical way to do the conversion. It apparently does nothing if given an Array, calls .to_a if that's present, and if not it just wraps its argument in an Array.
Regarding whether to_a is deprecated...well, I said "the default":
Ross-Harveys-MacBook-Pro:puppet_sd ross$ irb
irb(main):001:0> class X; X; end.new.to_a
(irb):1: warning: default `to_a' will be obsolete
They are Defined in Ruby Kernel Module, like:
Array(), Complex(), Float(), Integer(), Rational(), Stirng(), etc.
I found those method references in Dave Thomas's Pickaxe book "Progamming Ruby 1.9", page 555.
For example: Array(arg) will convert arg as an Array, following are copied from the book:
"Returns arg as an Array. First tries to call rg.to_ary, then arg.to_a. If both fail, creates a single element array containing arg( or an empty array if arg is nil)."
ex. Array(1..5) # => [1, 2, 3, 4, 5]
From what I understand, the simple version is like this:
object.to_a tries to convert 'object' to an Array using a class member function.
Array(object) tries to make a new Array using 'object'.
I can re-define what .to_a means for a given class (it is just another member after all). The Array(...) call is defined in Kernel so it behaves the same for any class. I typically use type conversions of the style Array(...) when I don't know ahead of time what type of object will be passed in. It's better at handling cases where an object doesn't know how to convert itself to an array or can't be converted to an array. If the object to be converted is the result of a long or complex expression, using the Array(...) style is often clearer. I save the .to_a form for instances when I know the class of the object and exactly what to expect from the output of .to_a (mostly instances when I have written or modified the .to_a member function myself).

Resources