The Whiz of Oz
The Whiz of Oz

Reputation: 7043

How to pass an object method inside a Ruby block as an argument?

In order to avoid repetition I have this presenter method to generate social links of a company page:

  def social
    networks = ['facebook', 'instagram', 'youtube', 'twitter']
    networks.each do |network|
      h.concat h.link_to h.image_tag("icons/#{network}.png"), @company.network, target: '_blank' unless @company.network.blank?
    end
  end

However the block argument acts as an object method, and I don't want that. How would I pass actual array values to the object here? I am currently getting the 'undefined method Network for obj Company...'

Update:

Given that only Facebook and Twitter fields are filled, I would like my outupd to be:

<a href="link to facebook"><img src='icons/facebook.png'></a>
<a href="link to twitter"><img src='icons/twitter.png'></a>

Upvotes: 0

Views: 165

Answers (1)

Milan K&#246;pke
Milan K&#246;pke

Reputation: 1133

You can send the value of the network variable to the object:

def social
  networks = ['facebook', 'instagram', 'youtube', 'twitter']
  networks.each do |network|
    company_network = @company.send(network)
    h.concat h.link_to h.image_tag("icons/#{network}.png"), company_network, target: '_blank' unless company_network.blank?
  end
end

For this to work, your object @company needs to respond to the messages/methods facebook, instagram, youtube, twitter.

A better way would be to implement a networks method which returns a hash with the name of the available networks as key and their link as value:

class Company
  AVAILABLE_NETWORKS = %i(facebook instagram youtube twitter)
  attr_accessor AVAILABLE_NETWORKS

  def networks
    AVAILABLE_NETWORKS.each_with_object{|network|
      { network: send(network) }
    end.reject{|k,v| v.blank? }
  end

end

You should also write your helper method in a way that makes it independent of the context (reusable) by eliminating the dependency on the @company instance and replace it with a parameter. In the method itself you then just need to iterate over the hash to get the network names and links.

def social(company)
  company.networks.each do |name, link|
    h.concat h.link_to h.image_tag("icons/#{name}.png"), link, target: '_blank'
  end
end

Upvotes: 2

Related Questions