Ruby: How to Chain Multiple Method Calls Together with "Send"

Ruby: How to chain multiple method calls together with send

I just ran across this and it really begs for inject:

def send_chain(arr)
arr.inject(self) {|o, a| o.send(a) }
end

Rails chain multiple commands to send method with arguments

You can use eval instead.

eval("Doctor.last.appointments.first")
=> #<Appointment id: 75, appointment_date: "2014-06-11", patient_id: 47, doctor_id: 5, created_at: "2014-12-23 18:55:13", updated_at: "2014-12-23 18:55:13", time_slot_id: 40, video_call_token: nil, call_state: "pending", payment_state: "unpaid", session_id: nil, manual_payment_at: nil, performed_video_call: false>

Ruby convention for chaining calls over multiple lines

There is actually a section on that in the Ruby style guide:

Adopt a consistent multi-line method chaining style. There are two
popular styles in the Ruby community, both of which are considered
good - leading . (Option A) and trailing . (Option B).

  • (Option A) When continuing a chained method invocation on
    another line keep the . on the second line.

    # bad - need to consult first line to understand second line
    one.two.three.
    four

    # good - it's immediately clear what's going on the second line
    one.two.three
    .four
  • (Option B) When continuing a chained method invocation on another line,
    include the . on the first line to indicate that the
    expression continues.

    # bad - need to read ahead to the second line to know that the chain continues
    one.two.three
    .four

    # good - it's immediately clear that the expression continues beyond the first line
    one.two.three.
    four

A discussion on the merits of both alternative styles can be found
here.

How to chain a method call to a `do ... end` block in Ruby?

yes, you can call a method here.

In your case,

array_variable = collection.map do |param|
# some value with param
end.compact

OR

array_variable = collection.map{ |param| some value with param }.compact

As pointed out by @Stefan, assignment is not required, you can directly use return and if that's the last line of method you can omit return too..

How do i invoke a method chain using map method, in ruby?

You can pass a block to map and put your expression within the block. Each member of the enumerable will be yielded in succession to the block.

category_ids = categories.map {|c| c._id.to_s }

Ruby/Rails - Chain unknown number of method calls

I created following query which will work on any model and associated chained query array.

def chain_queries_on(klass, arr)
arr.inject(klass) do |relation, query|
begin
relation.send(query[0], *query[1..-1])
rescue
break;
end
end
end

I tested in local for following test,

arr = [['where', {id: [1,2]}], ['where', {first_name: 'Shobiz'}]]

chain_queries_on(Article, arr)

Query fired is like below to return proper output,

Article Load (0.9ms)  SELECT `article`.* FROM `article` WHERE `article`.`id` IN (1, 2) AND `article`.`first_name` = 'Shobiz'  ORDER BY created_at desc

Note-1: few noticeable cases

  1. for empty arr, it will return class we passed as first argument in method.

  2. It will return nil in case of error. Error can occur if we use pluck which will return array (output which is not chain-able) or if we do not pass class as first parameter etc.

More modification can be done for improvement in above & avoid edge cases.

Note-2: improvements

You can define this method as a class method for Object class also with one argument (i.e. array) and call directly on class like,

# renamed to make concise
Article.chain_queries(arr)
User.chain_queries(arr)

Inside method, use self instead of klass



Related Topics



Leave a reply



Submit