This question already has answers here:
What do you call the -> operator in Ruby?
(3 answers)
Closed 8 years ago.
I was browsing Friendly_id gem code base and I found line with following assignment:
#defaults ||= ->(config) {config.use :reserved}
My questions are:
How do I interpret this line of code?
What does exactly -> do and what does it mean?
Is there any articles about it, how to use it?(Official Ruby documentation would be nice, I haven't found it)
Thank you for your help
This denotes the lambda. With this you are latching an anonymous function which takes a parameter config and computes a block using that variable.
The above expression can also be defined as:
#defaults ||= lambda {|config| config.use :reserved}
Proc is similar to lambda in Ruby, apart from few differences of return and break pattern. Proc can be called as a block saved as an object, while lambda is a method saved as an object. They find their roots in functional programming.
In short, a lambda is a named procedure, which can be saved as an object and can be called later.
inc = ->x{ x + 1 }
inc.call(3)
#=> 4
One common and interesting example of lambda is Rails Scope, where a method is simply assigned in name scope as lambda and can be later used as an action while ActiveRecord querying.
Related
My question is not an error, it is for understanding. As I'm new to Rails, I can't read all the code yet.
what does (&:id) do after .map
#user_cnae_classifications = user.cnae_classifications.map(&:id)
what is the difference of .map with it and without it?
in this method call:
UserCnaeClassification.create(
user: #user,
cnae_classification_id: id
)
How do I read that part of the code...
user: #user,
cnae_classification_id: id
are they keys and values?
1 )
You should read some tutorials on map to get acquainted.
https://www.rubyguides.com/2018/10/ruby-map-method
But the short answer is that running user.cnae_classifications.map(&:id) will loop over all cnae_classifications and extract the id from them and put them all into an array. The & character allows for map shorthand to avoid passing an entire block.
From the link above:
2 )
The #create method can accept a key-value hash of known attributes (known to the class in question, in this case that is UserCnaeClassification) to assign upon creation. So you're basically right, they are key-value pairs but they are specific to this class/object. Those same keys might not work on another class/object.
Additional reading: https://guides.rubyonrails.org/active_record_basics.html#create
what does (&:id) do after .map
The syntax map(&:method) is equivalent to:
object.map do |i|
i.method
end
The complete explanation is that the & operator is used to convert any Ruby object that responds to to_proc into a Proc, which encapsulates a block of code. In this case, the Symbol object (:id) is converted into the block of code above.
If you're interested in learning more about it, notice this is pure Ruby, not Rails-specific. Check the documentation for Proc.
In this method call:
How do I read that part of the code...
are they keys and values?
These are keyword arguments. It's a way to name the parameters of a method to explicitly tell the reader what each value should be. Just be aware that the behavior of methods accepting hashes as keyword arguments is deprecated, as seen in this official post.
The .map(&:id) is a shorthand for the longer form of .map { |x| x.id }.
Some interesting things to say: if you're using database (ORM - ActiveRecord), you will see that writing map(&:id) could be helpful. There also exists method called pluck, which does similiar things, but it's a little faster.
Usage:
Also pluck doesn't work with regular Arrays.
This question already has answers here:
What does map(&:name) mean in Ruby?
(17 answers)
Closed 3 years ago.
I'm walking through the example project in the Rails 5 Test Prescriptions - Build a Healthy Codebase (published date: 2018) book and encountering this method:
#pages 29-30 of the book
class Project
.
.
def done?
tasks.all?(&:complete?) #only this line confused me, especially the `&` part
end
end
the syntax looks really strange to me since I just learned Ruby & Rails for more than one month..any hints just for pointing me to where I should read would be really appreciated
& is for passing block to method as a block (also used the other way in parameter list to make implicit block a parameter), it implicitly calls to_proc on passed object.
Symbol#to_proc for :symbol makes a proc{|param| param.symbol }
So your code is equvalent to tasks.all?{|task| task.complete? }
This question already has answers here:
What does map(&:name) mean in Ruby?
(17 answers)
Closed 9 years ago.
Can any one explain the use of '&' in this piece of ruby code?
s.feature_addons.select(&:is_active?)
It means:
s.feature_addons.select { |addon| addon.is_active? }
The & calls to_proc on the object, and passes it as a block to the method.
class Symbol
def to_proc
Proc.new { |*args| args.shift.__send__(self, *args) }
end
end
U can define to_proc method in other classes: Examples
That's a shortcut for to_proc. For example, the code you provided is the equivalent of:
s.feature_addons.select {|addon| addon.is_active?}
Some old documentation for it can be found here:
http://apidock.com/rails/Symbol/to_proc (when it was provided by ActiveSupport)
It then became a part of Ruby core in 1.9
http://www.ruby-doc.org/core-1.9.3/Symbol.html
You can use this syntax as shorthand for methods to apply to an entire collection.
It is functionally the same as:
s.feature_addons.select { |a| a.is_active? }
You can use it with any collections, such as:
User.all.map(&:id)
etc
This question already has answers here:
Is there an inverse 'member?' method in ruby?
(5 answers)
Closed 8 years ago.
So a fairly common pattern I've run up against is something like this:
[:offer, :message].include? message.message_type
The inversion of wording there messes me up. So I wrote this little monkey patch for Symbol in specific.
def in? *scope
scope.include? self
end
So now I can do the previous this way:
message.message_type.in? :offer, :message
This works fine and I'm happy with it, but occasionally I need similar functionality for other objects. Model objects in Rails apps being the most common case but strings occasionally, etc.
What kind of issues would I run into if I monkey patched this directly into Object?
Rails (ActiveSupport) already patches Object with this method. Here is the documentation: http://api.rubyonrails.org/classes/Object.html#method-i-in-3F.
Returns true if this object is included in the argument. Argument must be any object which responds to #include?. Usage:
characters = ["Konata", "Kagami", "Tsukasa"]
"Konata".in?(characters) # => true
This will throw an ArgumentError if the argument doesn’t respond to #include?.
This question already has an answer here:
naked asterisk as parameter in method definition: def f(*)
(1 answer)
Closed 10 years ago.
When I was reading Rails code, I found this
def save(*)
create_or_update || raise(RecordNotSaved)
end
What does the * do? :O
I know what happens when we use it like *args, but in this case, it's just plain *.
ref https://github.com/rails/rails/blob/master/activerecord/lib/active_record/persistence.rb#L119
It means the same thing as it does when used with a parameter name: gobble up all the remaining arguments. Except, since there is no name to bind them to, the arguments are inaccessible. In other words: it takes any number of arguments but ignores them all.
Note that there actually is one way to use the arguments: when you call super without an argument list, the arguments get forwarded as-is to the superclass method.
In this specific case, save doesn't take any arguments. That's what happens with a naked splat. But, as you may be aware, calling save on an ActiveRecord model accepts options because this method gets overridden by ActiveRecord::Validations here:
https://github.com/rails/rails/blob/v3.1.3/activerecord/lib/active_record/validations.rb#L47
# The validation process on save can be skipped by passing <tt>:validate => false</tt>. The regular Base#save method is
# replaced with this when the validations module is mixed in, which it is by default.
def save(options={})
perform_validations(options) ? super : false
end