I have a repeated methods in my model and I want to put those codes into one place and just want to access it into my model.
My model have few methods such as:
class ProductionProductivity7 < ApplicationRecord
def self.import1(file)
spreadsheet = Roo::Spreadsheet.open(file.path)
header = spreadsheet.row(1)
(2..spreadsheet.last_row).each do |i|
row = Hash[[header, spreadsheet.row(i)].transpose]
puts row.to_hash
product = find_by(id: row["id"]) || new
product.attributes = row.to_hash
product.save!
end
end
def self.search(search,compare)
if search == "All"
all.order(:id)
elsif compare == "Bihar vs District"
where("Districts = ? OR Districts = ?", search, "Bihar")
else
where(Districts: search)
end
end
end
There are 3 more methods like this , I want to put this code block into helper and just want to call it inside model. For that I have tried this put these codes into my helper. And I am calling it using:
include ApplicationController.ProductionProductivity7sHelper
I am including this inside my model but I am getting this error:
undefined method `ProductionProductivity7sHelper' for ApplicationController:Class
My controller code is like this:
def test
@ProductionProductivity7s = ProductionProductivity7.search(params[:search],compare)
a = ProductionProductivity7.query(@ProductionProductivity7s,params[:year],rain_fall_type,views,compare)
end
I have added a module name code.rb in app folder.
module Code
def search(search_scope,compare)
if search_scope == "All"
all.order(:id)
elsif compare == "Bihar vs District"
where("Districts = ? OR Districts = ?", search_scope, "Bihar")
else
where(Districts: search_scope)
end
end
end
I just want to write all of my methods of my model somewhere it can be either module or helper without changing anything. Is it possible I just want this code block in my model.
I am adding whole controller code and model code in gist files. Please have a look. My controller and Model code link
I am getting this error:
undefined method `search' for #<Class:0x00007ff115974fd8> Did you mean? search1
How about just making a module like:
module Import1
def import1(file)
spreadsheet = Roo::Spreadsheet.open(file.path)
header = spreadsheet.row(1)
(2..spreadsheet.last_row).each do |i|
row = Hash[[header, spreadsheet.row(i)].transpose]
puts row.to_hash
product = find_by(id: row["id"]) || new
product.attributes = row.to_hash
product.save!
end
end
def search(search_scope,compare)
if search_scope == "All"
all.order(:id)
elsif compare == "Bihar vs District"
where("Districts = ? OR Districts = ?", search_scope, "Bihar")
else
where(Districts: search_scope)
end
end
end
I think I would put it somewhere in your app
folder so that you don't have problems with autoloading. You could put it in your root app
folder, but that seems messy to me. You could also put it in your models
folder, but then you have two very different kinds of things in the same folder which also seems messy to me. I think I would be tempted to create a new folder, something like app/model_modules
or perhaps app/shared_model_modules
and put your import_1.rb
file in there. Then, it's clear what the file is.
And then do:
class ProductionProductivity7 < ApplicationRecord
extend Import1
end
Or, how about using a service instead of a helper? IMO, it makes it more explicit what is going on whereas helpers can obsfucate where code lives.
A bare bones BaseService
might look like:
class BaseService
attr_accessor :args
class << self
def call(args=nil)
new(args).call
end
end # Class Methods
#=======================================================================
# Instance Methods
#=======================================================================
def initialize(args)
@args = args || {}
assign_args
end
private
def assign_args
args.each do |k,v|
class_eval do
attr_accessor k
end
send("#{k}=",v)
end
end
end
Then, your file import service might look something like:
class ImportFileService < BaseService
def call
spreadsheet = Roo::Spreadsheet.open(file.path)
header = spreadsheet.row(1)
(2..spreadsheet.last_row).each do |i|
row = Hash[[header, spreadsheet.row(i)].transpose]
puts row.to_hash
product = klass.find_or_initialize_by(id: row["id"])
product.attributes = row.to_hash
product.save!
end
end
end
And you would call your service something like:
ImportFileService.call(file: file, klass: ProductionProductivity7)