哪种是动态使用变量静态数据的正确方法

时间:2015-05-24 17:46:44

标签: ruby database data-structures

遵循基本原则,构建程序的首选方法及其数据可以变化,但用于实现相同的标准"任务?它应该很容易扩展,以包括更多的提供者。

例如:

require 'mechanize'
require 'open-uri'

class AccountFetcher 

    @@providers = {}
    @@providers['provider_a'] = [
        'http://url_for_login_form.com/', 'name_of_form',
         # the number of fields can vary between different providers
        [ ['name_of_field', 'value_for_it'], ['another_field', 'another_value'] ],
        ['name for username field', 'name for password field']
    ]
    @@providers['provider_b'] = [
        'http://another_url.com/', 'another_form_name',
        [
            # array of more fields that are specific to this form 
        ],
        ['name for username field', 'name for password field'] 
    ] 


    # looks more nice using AccountFetcher.accounts opposed to @@accounts 
    def self.accounts 
       @@providers
    end 


    # example of a method that uses information that can vary
    def self.fetch_form(agent, account_type)

        # the first element in the array will always be the url
        page = agent.get(AccountFetcher.accounts[account_type][0])

        # the second element in the array will always be the name of the form
        form = page.form(AccountFetcher.accounts[account_type][1])
    end 


    def self.initialize_form(agent, account_type)

        form = AccountFetcher.fetch_form(agent, account_type)

        # will cycle through all fields that require 'pre-filling'
        AccountFetcher.accounts[account_type][2].each do |f|

            # f[0] will always be the name of the field and f[1] will
            # always be the value for the field; however, the amount of
            # fields may vary
            form.field_with(:name => f[0]).value = f[1]
        end 

        form 
    end  

所以一般的想法是使用一个由散列组成的类变量,并且包含包含相应数据元素的数组。我需要为每个具有类似功能的类执行此操作。

我的另一个想法是替换类变量,而是将每个提供程序转换为可由其他类访问的类数据库。所以provider_a会变成:

class ProviderA

    # all the possible information needed
    # methods will have similar names across all the different providers
end

可以选择合适的提供者

class Providers

    @@p_providers = {}
    @@p_providers['provider a'] = ProviderA.new
    @@p_providers['provider b'] = ProviderB.new
    @@p_providers['provider c'] = ProviderC.new
    @@p_providers['provider d'] = ProviderD.new

    def self.return_provider(name)
        @@p_providers[name]
    end
end    

前者或后者的解决方案更合适吗?或者是否有更多的红宝石'解?

1 个答案:

答案 0 :(得分:1)

I would store this configuration values in an external YAML file. Your configuration file could looke like this:

# config/providers.yaml
provider_a:
  url: 'http://url_for_login_form.com/'
  name: 'name_of_form'
  fields:
    - name: 'name_of_field'
      value: 'value_for_it'
    - name: 'another_field'
      value: 'another_value'
provider_b:
  url: 'http://...'
  ...

You could load that file with YAML.file_file that returns nested hash in this example.

require 'yaml'
def AccountFetcher
  def self.accounts
    @accounts ||= YAML.parse_file("config/providers.yaml")
  end
  #...
end

You may want to consider using a Gem like has_configuration that makes handling the data structure a bit easier.