Reputation: 1688
Structure of ruby file is as shown below,
market
|__abcd
|__classification
|__for_sale_mobile_phone.rb
|__catalogues
|__mobile_phone_brands
|__acer.rb
|__apple.rb
|__samsung.rb
In for_sale_mobile_phone.rb
, I like to include all brands of mobile_phone_brands
under a block.
I m trying to include brands in below fashion,
.....
c.tree_field :brand, { child_key: :model } do |b|
Dir[
File.dirname(__FILE__) + '/catalogues/mobile_phone_brands/*.rb'
].each { |brand| load brand }
b.required = true
end
.....
here is how brand file looks like. for example, apple.rb
b.value "apple" do |brand|
brand.value "6plus"
brand.value "6s"
brand.value "6s-plus"
brand.value "se"
brand.value "7"
brand.value "7-plus"
brand.value "other-model"
end
I m getting below error,
undefined local variable or method `b' on line 1: apple.rb
How can I include file under a block scope?
Thanks in advance!
Upvotes: 0
Views: 221
Reputation: 1688
The way I figured out is by using eval
but cautious read up is-eval-supposed-to-be-nasty, eval
works for me as I'm not using user input.
To make any code in different file, execute as the code written in the place of call. Use eval(File.read(file_path)
.....
c.tree_field :brand, { child_key: :model } do |b|
Dir[
File.dirname(__FILE__) + '/catalogues/mobile_phone_brands/*.rb'
].each { |brand| eval(File.read(brand)) }
b.required = true
end
.....
Upvotes: 0
Reputation: 1683
You should separate file "loading" from function execution. Redefine your file like this.
class AppleLoader
def self.load(b)
b.value "apple" do |brand|
brand.value "6plus"
brand.value "6s"
brand.value "6s-plus"
brand.value "se"
brand.value "7"
brand.value "7-plus"
brand.value "other-model"
end
end
end
On top of file you load required classes like this:
require '/catalogues/mobile_phone_brands/apple_loader.rb'
And when you want to load Apple brand in the b
object:
AppleLoader.load b
Better Approach:
To me it feels like Apple.rb
defers from Samsung.rb
only in terms of data. If that's the case, and functionality for both of them are same then I would rather:
put that data in a Yaml file(brands.yml
) instead of rb file.
brands:
apple: ["6plus", "6s"]
samsung: ["galaxy"]
Have just one common loader called BrandLoader
class BrandLoader
def self.load(b, brand_name, values)
b.value brand_name do |brand|
brand_values.each do |value|
brand.value value
end
end
end
end
Iterate over brands by reading Yaml
configurations = YAML.load "brands.yml"
configurations["brands"].each do |brand_name, values|
BrandLoader.load(b, brand_name, values)
end
Upvotes: 1