Rails Global Function: Pass Object Function Is Called On [duplicate] - ruby-on-rails

This question already has answers here:
How to make a method available to all controllers? And how to all models?
(3 answers)
Closed 5 years ago.
I want to create a global function, which I will put in my application controller.
For the sake of making this question simple, here is an example of what I would do:
In my /application_controller.rb
def self.global_function(device)
p device
end
And in the controller I'm working in:
def some_function
global_function(Device.find(some_id))
end
That works, but I would like to have it work, for example, as the .last method does. The end result would allow me to call like this instead:
def some_function
Device.find(some_id).global_function
end
Still passing the device object over, but without the need for parameters.
I can't give a reason for why I prefer one over the other, aside from aesthetics. If there are any drawbacks from using one way over the other, I'd like to know that as well. Thanks

You're confused about what is a function vs what is a method.
This has nothing to do with making a "global function". You just need to define a plain old method on Device:
class Device < ActiveRecord::Base
def some_method
# do something with `self`
end
end
This will let you invoke global_method on any Device instance, such as the one returned by find:
Device.find(some_id).some_method

Related

RIght way of writing module methods in Ruby

what is right way of writing module? is it only used to stock some peace of code to minimize the number of lines, or is it something much more important than that
I have used and seen ways of writing module, I am working on setting up correct way to define and standardised module. this example is kind of controller code that we use in rails
Way 1 :-
module B
extend ActiveSupport::Concern
def process_items
# do somthing...
#items.pluck(:names)
end
end
Class A
include B
def index
#items = Item.all
#item_names = process_items
end
end
Way 2 :-
module B
extend ActiveSupport::Concern
def process_items(items)
# do somthing...
items.pluck(:names)
end
end
Class A
include B
def index
#items = Item.all
#item_names = process_items(#items)
end
end
Way 1 :-
When I see this independently, its not much readable as I don't know how #items appeared in this method
Unit testing would be hard for method as its dependent
Way 2 :-
Looking at method I can see input is coming we are processing it and returning it back (readablity is good)
Unit testing is easy to this, we wll call method pass what it needs and expect
The way I see modules should be independent, self explanatory, it should be generic so that can be used in any class, kind of helpers. But other way could be dependent on where we use modules
We are using modules like in rails
We use conccern in models, when we call module method we can use self.<field> we don't need to pass anything because instance variable is supposed to be accesssable in every instance method
View helpers are modules I see they put logic into it hard to understand how the variable come from may be instance variable or params, what about making it method which accept somthing and return it back
Concerns on controllers, like the example I have given
I would like to have thoughts on this, what is best approach out of it? is it something which can be standarise or it is more situational or I don't know yet :)
Note: -
I was looking at this question but answer given on this question is no more valid as referenced links are not working.
Right Way to Use Module
The difference here is practically academic, as if you have attr_reader :x then both #x and x will have the same meaning.
It's understood that within a mixin module you will be referencing methods and/or variables that are part of the class or module doing the "mixing in". As such, seeing #x, or in your case, #items, should not come as a real surprise.
If you want to add it as an explicit argument you're sort of missing a lot of the benefits of using a mixin in the first place. You don't need to mix it in at all, you can just use it like B.process_items(...). In other words, your second approach is having an identity crisis. Is it a stand-alone module that includes Concern for no reason, or a weak mixin?
When it comes to testing, you must test the mixin in a module or class which implements the required features. In this case you need either an #items variable, or an items method, and that must have a value of the expected type.
This should be documented somewhere for clarity, but is effectively an implicit contract with anyone using this module.

How to make a custom method that can be used anywhere in rails app

I wish to make a custom method (e.g. def plus_two(x) x + 2 end and have it be accessible everywhere within the app - that is, accessible in the controller, model, console, views, tests, and any other .rb files. I currently have the same method defined in many areas of the app, and wish to make it DRY
How can this be achieved?
Note: I don't mind if calling the method requires prepending something (I have seen some answers where methods are prepended with :: or with a namespace, but otherwise have a preference to keep code succinct where possible
I have done some reading at similar questions (e.g. this one) but I can't quite get it
Reading the comments it seems like you are just looking for a clear and simple example of a method that is available everywhere in your application:
# in app/models/calculator.rb
module Calculator
def self.plus_two(x)
x + 2
end
end
Which can be called like this:
Calculator.plus_two(8)
#=> 10

Ruby define method to return proc which makes use of an argument [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
In Ruby, I'd like to define a method that takes an argument, which returns a proc full of methods that make use of that argument. Something like the following
def test(word)
proc do
def hello
puts word
end
end
end
my_proc = test('hello')
my_proc.call.hello
When running this code, the local variable 'word' is undefined
To give some more context, I am trying to make use of association extensions, which allow you to provide a block of methods to an association to define extra helper methods on the association. I have some methods I'd like to use on several similar active record models with similar associations, but they only differ by a certain symbol when making calls (the name of the join table passed to through on a has_many relationship). So ideally I was thinking of making a method that accepts that symbol, which could then be used in the implementation of the association extension.
Your example has two problems:
You can't call a "proc full of methods" like that -- it'll work as an association extension, but there the block is evaluated as a module body, not called.
The def keyword resets the local variable scope. To get a value into a function, you can either define it using define_method instead (that block retains surrounding scope), or put the value somewhere else the function will be able to find it (a class variable, for example).
def test(word)
proc do
define_method(:hello) do
puts word
end
end
end
Class.new(&test("hello")).new.hello
Separately, if you're defining approximately the same method on several associations, there might be a simpler path by defining them as class-level scopes.
This is like your call.
def test(word)
proc do
define_method :hello do
puts word
end
end
end
my_proc = test('hello world')
my_proc.call.hello
Ad it returns # => hello world
Edit: Picking up the #engineersmnky comment, after that you can simply call hello.
You can find more informations about here: Is it possible to have Methods inside Methods?

The meaning of `*` when using as a param(not like *arg, just *) [duplicate]

This question already has an answer here:
naked asterisk as parameter in method definition: def f(*)
(1 answer)
Closed 10 years ago.
When I was reading Rails code, I found this
def save(*)
create_or_update || raise(RecordNotSaved)
end
What does the * do? :O
I know what happens when we use it like *args, but in this case, it's just plain *.
ref https://github.com/rails/rails/blob/master/activerecord/lib/active_record/persistence.rb#L119
It means the same thing as it does when used with a parameter name: gobble up all the remaining arguments. Except, since there is no name to bind them to, the arguments are inaccessible. In other words: it takes any number of arguments but ignores them all.
Note that there actually is one way to use the arguments: when you call super without an argument list, the arguments get forwarded as-is to the superclass method.
In this specific case, save doesn't take any arguments. That's what happens with a naked splat. But, as you may be aware, calling save on an ActiveRecord model accepts options because this method gets overridden by ActiveRecord::Validations here:
https://github.com/rails/rails/blob/v3.1.3/activerecord/lib/active_record/validations.rb#L47
# The validation process on save can be skipped by passing <tt>:validate => false</tt>. The regular Base#save method is
# replaced with this when the validations module is mixed in, which it is by default.
def save(options={})
perform_validations(options) ? super : false
end

How do I use parameters in a constructor in a rails model

I trying to learn tdd using RSpec. I took this example from a cheat sheet I found online and am a bit confused as to how I would implement it. To add MovieList.new is automatic but how would I go about adding a parameter when it is already handled with ActiveRecord. And then to add the 'forward' method as well.
describe "forward" do
it "should jump to a next movie" do
next_movie = MovieList.new(2).forward
next_movie.track_number.should == 2
end
end
If this is a test for a MovieList class, create a class called MovieList.
Then in your constructor for that class, make sure it takes in a parameter called track_number, in your test that's the 2.
Then create a method called forward to do whatever you need it to do?
Here's a good example of where I'm going with this:
http://rspec.info/
This may sound ambiguous, but so was the question.
EDIT:
This is a rough idea of how to create a new MovieList class and initialize it with a parameter called track_number.
def MovieList
attr_accessor :track_number
def initialize(track_number)
#track_number = track_number
end
# You can define all your class methods below, you
# can start with forward.
def forward
# do something...
end
end
movie = Movie.new(:track_number => 2)
movie.forward
I am not sure what forward does in your example because you seem to be initializing track_number to 2 then calling forward. I would have expected track_number to increment but your test is checking to see if it's 2 still.
Note, I don't believe you need to change your constructor to take the parameter as long as you pass it in as a hash (the single member hash is implied in my example)...can someone verify or refute this last assertion?

Resources