Rails: Model instance method or helper method?
Go with the first (keep in model), also because you might want to do other stuff, like combined indexes :)
Instance Methods vs. Class methods For a Helper Class - Ruby, Rails
If you don't need to customize the state of each instance
(via initialize
and instance variables), it makes sense to make class methods
instead. If you're going with class methods, you could make your Class
a Module
and it would have the same effect.
If you're using a purely functional paradigm when programming, you wouldn't
ever use instance methods. Instead, you'd pass all your needed data as
arguments. I'm not recommending this approach because OOP simply makes things
easier in many cases, but for this situation, class methods make sense to me.
Functional programming is useful (methods like map
, reduce
, or the proc shorthand),
but I don't see any reason to use it instead of OOP.
Run a helper method on a model class method
You have to extend
the module instead of include
.
extend ModelHelper
include
makes the methods available as instance methods of Foo
. That means, you can call the method method_i_want_to_use
on instances of Foo
, not on Foo
itself. If you want to call on Foo
itself, then use extend
.
module ModelHelper
def method_i_want_to_use
puts "I want to use this method"
end
end
class Foo
extend ModelHelper
def self.bar
method_i_want_to_use
end
end
Foo.bar
# >> I want to use this method
Rails 4: Why a helper included in a class is inherited but the instance method of a class is not
There is quite a lot of things which are wrong here. First of all, you execute include
method outside of the class. That will result the module to be included within an Object
class and hence will make all the methods available on pretty much every single object in your application. This is why you can use @items.number_to_currency
. You also are able to use nil.number_to_currency
, 15.5.number_to_currency
, false.number_to_currency
. This is just wrong.
Now, even if you move it inside the class, it will still not work. @items
is an instance of ActiveRecord::Relations
(most likely) or a collection of items. Your method is an instance method and can only be called on a single item.
That being said, this method should not even be an instance method of your Item, as this breaks MVC pattern. This method only purpose is to display given value in dollars, which is typical view concern. It doesn't even use any of the models attributes. It should be placed within helpers.
Using a helper method to set an instance variable
You can use "controller concern", for example:
app/controllers/concerns/steam_pressure_setup.rb
module SteamPressureSetup
extend ActiveSupport::Concern
included do
before_action: set_max_stream_pressure
end
def set_max_stream_pressure
# ...
end
end
Then include it in your controllers which need it.
app/controllers/my_controller.rb
class MyController < ApplicationController
include SteamPressureSetup
# ...
end
Ref: https://api.rubyonrails.org/classes/ActiveSupport/Concern.html
Helper or Class Method for this use case - Rails
Two things. First, this:
# user.rb
def first_name
self.full_name.split[0]
end
is not a class method. It's an instance method.
Second, IMO, you want as little logic in your views as possible. And, your views shouldn't know anything about your models or their internal workings. What happens if, for some reason, your model or your data changes and full_name.split[0]
is no longer the way to get at the first name? Then, you'll have to remember that you put that logic in a helper and go change it there.
So, go with choice #2 - the instance method.
Is using a helper method in a model possible and, more importantly, appropriate?
Models aren't the appropriate place to put presentation logic, which is what this is. This is what helper methods are for. A good rule of thumb is if it's not raw data coming out of a model, you're mixing presentation with domain.
It would be more appropriate to do something like:
# app/helpers/member_helper.rb
module MemberHelper
def last_seen(member)
if member.last_sign_in_at.nil?
"User hasn't signed in yet"
else
"Last seen #{distance_of_time_in_words(Time.now.localtime, member.last_sign_in_at.localtime, true, :highest_measure_only => true)} ago"
end
end
end
But to be honest, unless you're using something like this on a ton of pages in varying contexts, moving this code to a helper may be overkill vs leaving it in the view.
How to call Rails' model instance method from the console
It seems your were in the rails console before defining the method inside the model. That's making the the new method to your model unavailable in the rails console. So, just do reload!
(reloads the environment) and try the same again, and this time you will have the access to the method.
Related Topics
Case Expression Different in Ruby 1.9
Ruby 1.9.2 - Read and Parse a Remote CSV
Ruby - Extracting the Unique Values Per Key from an Array of Hashes
How to Extend Redcarpet to Support Auto Linking User Mentions
Write Array of Radix-2 Numeric Strings to Binary File in Ruby
Ruby: How to Check If a String Contains Multiple Items
Rails:Runtimeerror - Can't Modify Frozen Array When Running Rspec in Rails
Is There a Bug in Ruby Lookbehind Assertions (1.9/2.0)
Ruby on Rails Country/State Select Enigma
Authlogic Perishable_Token Resets on Every Request
Ruby Variable as Same Object (Pointers)
Array Typeerror: Can't Convert Fixnum into String
How to Do "Late" String Interpolation in Ruby
Ruby Daemons and Jruby - Alternative Options