rails can I call model inside initializer files - ruby-on-rails-5.2

I need to call model inside rack_attack.rb file to check ip is blocklisted or not any idea how to do that?
/config/initializer/rack_atack.rb

As long as your migrations were already executed and the table for the model in question already exists, I believe you will be able to call your model from the initializer file as usual: Model.method().
If you want to check if the table exists, you could do like this:
if ActiveRecord::Base.connection.table_exists? :settings
Model.method()
end
Finally, if you want to make sure all other initializers have run before running this one, you could add the following code to your initializer:
# config/initializers/rack_attack.rb
Rails.configuration.after_initialize do
Model.method()
end

Related

Is there a way to store an instance method inside a variable without running that function first? In Ruby

I am trying to store an instance method as a variable so I can pass it into a way to store logic on a menu I am building.
For example, I want my our_startup.prompt method to be stored in my start_game_ui.logic array. I am trying to do this using a start_game_ui.set_logic function which shovels arguments into the logic array. I would like to shovel 6 methods into the logic array so that when I run my final function to puts and receive input 1 - 6. If the user chooses 1 it should run the function in the first element of the array.
our_startup = Startup.new("No Name")
## START GAME UI ##
start_game_ui = UI.new("start_game_ui")
start_game_ui.menu_items = ["[1] - Yes", "[2] - Generate Another"]
##set up logic##
method1_test = our_startup.set_name("test")
rerun = start_game_ui.prompt
start_game_ui.set_logic(method1_test, rerun)
When I run this, my start_game_ui.prompt method will run. I want to store the start_game_ui.prompt method in that variable rerun without having the method run.
Once I run my final method and choose 1 it should return "test". However when I run this it runs start_game_ui.prompt and I don't want it to.
I hope you can understand what I mean. I have 2 classes UI and Startup if you couldn't already tell.
PLEASE DO NOT TELL ME I CAN DO method(:something) this does not help as it is an instance method being called by another instance. Unless you can tell me how to get that symbol to correspond with the correct method inside the instance. I've tried method(our_startup.prompt) and it does not work.
PLEASE DO NOT TELL ME I CAN DO method(:something) this does not help as it is an instance method being called by another instance.
I would really like to not tell you that, but unfortunately, that is the correct answer:
rerun = start_game_ui.method(:prompt)
# Then, later when you need to call it:
result = rerun.()
Not using Object#method, as you require in your question, leads to significant added complexity, e.g. by passing around the receiver and the name of the method separately:
rerun_receiver_and_message = [start_game_ui, :prompt]
# Then, later when you need to call it:
result = rerun_receiver_and_message.first.public_send(rerun_receiver_and_message.last)
The only thing you can store in variables and pass as arguments are objects.
Procs and Lambdas are objects, so you should be able to do something like
rerun = -> {start_game_ui.prompt}
start_game_ui.set_logic(method1_test, rerun)
rerun is storing the call to the method, not the results of the method
At the point where you need to execute the method, you would do
rerun.call
Note that Procs and Lambdas can also specify arguments, that you can supply at the time of the call.
I'm not sure if this helps with your problem, but hope it does.
If you'd like to get the instance method from inside the instance of your object, then you can use this: our_startup.method(:prompt)
I don't really understand what your end goal is, so I'm going to suggest you read up a little further on Ruby's object model and methods and provide you some guidance instead.
The method method returns an instance of Method (an object). If this is confusing, read it more slowly and check out the Method documentation. Whether the method being referenced by the argument is an instance method or not is irrelevant to the behavior of the method method.
Directly addressing something you said in the question: using method(:foo) does not call the referenced method (e.g. foo).
You can unbind a method from the source receiver (creating an UnboundMethod that can't be called) and rebind it to another receiver if you need to:
my_method_instance = some_string.method(:to_s)
# Now I can call `some_string.to_s` like so:
my_method_instance.to_s
# This isn't very useful for `to_s`, but it could be in other situations
method_instance = SomeModule::SomeHelper.method(:parse_html)
array_of_html_docs = array_of_strings.map(&method_instance)
# And you can unbind the method from the original receiver:
my_unbound_method_instance = my_method_instance.unbind
# And rebind it elsewhere
my_unbound_method_instance.bind(some_other_receiver)
my_unbound_method_instance.call(args) # receiver is `some_other_receiver` here

Using Grape to create an API with just Ruby objects instead of a database or Rails

I am trying to use Grape to create an API using only Ruby objects. I do not want to use a database/Rails/ActiveSupport/etc -- just Rack, Ruby, and Grape.
I have defined a class for a Directory that I want to interact with through the API. So Directory#sort_by("last_name") returns JSON data with a list of People objects in my Directory. I also have a method Directory#create_person(attributes) that takes a string and uses it to add Person objects to the Directory. The directory is populated with people upon creation.
I am new to working with Rack and Grape, so I'm not sure where/how to create my Directory object and have it accessible through the GETs/POSTs in my Grape API class. Using a class variable inside this class appears to work, i.e.,:
module API
class DirectoryAPI < Grape::API
format 'json'
##directory = Directory.new("1.txt", "2.txt", "3.txt")
get 'last_name' do
##directory.sort_by("last_name")
end
end
end
but using class variables just seems wrong. Is there any better/cleaner way to create my Directory object? Perhaps inside my config.ru file? Or could I do it through a class method inside of Directory somehow?
What you are looking for is a singleton:
Usually singletons are used for centralized management of internal or external resources and they provide a global point of access to themselves.
Unfortunately, Ruby just doesn't play well with singletons. But you can use a "class consisting of only class methods," the second strategy advocated in this article.
I believe that you are working on a coding challenge that I completed a few months ago. In my answer, I used a "class consisting of only class methods" called API::Store. Here's the output from rspec -fd:
API::Store
::add
adds record to store
appends data line to file
::has_line?
instantiates a record from the data line
without the record in the store
should equal false
with the record in the store
should equal true
::new
should raise NoMethodError
::records
with original file
on initial access
should eq Records
on subsequent access
should eq Records
when file replaced
should eq OtherRecords
Finished in 0.07199 seconds (files took 2.68 seconds to load)
9 examples, 0 failures
Note that Store can't be instantiated; it throws a NoMethodError if you try. That's not a problem, though. In the Grape endpoint you can call Store.records to access the data.
As for sorting the records, this should be done in another class. Why should a Store or a Directory be sorting the data in its files?
Finally, you asked where to do the initial preparation (not initialization, of course). You can prepare your singleton in config.ru, so that it is ready when the application starts:
# config.ru
# load application code here
file = File.open('data/records.txt', 'a+')
at_exit { file.close }
API::Store.file = file
run API::Base
The challenge's instructions say "You may use any resources you need to complete it," so presumably, asking on Stack Overflow is allowed. If you are doing this challenge for a job application, please do mention so when you ask questions, because it's only fair for those answering to be informed. It would be wise to also mention at your interview that you got help on SO. Good luck, and happy coding.
The main problem I see with your example is not the use of class variables exactly, but instantiating your data inline in the API controller code. Ideally the data should be more self-contained, so you can access the exact same data from other places in your code. If you make an API similar to a light-weight data access module, then you will be using a familiar pattern in your route controllers - also it will become easy to migrate to using SQL or other data store if and when you need to.
There are lots of valid approaches, but I might create a new singleton object to represent your data source, and connect that to your hard-coded data as if it were tables. The end result here would feel a little like using Sequel (but you could follow any other pattern that you prefer):
inline_data.rb
module InlineDB
TABLES = Hash[
:directory => Directory.new("1.txt", "2.txt", "3.txt")
]
def self.[] table_name
TABLES[table_name]
end
end
app.rb
require_relative 'inline_data' # actual path may be more structured
module API
class DirectoryAPI < Grape::API
format 'json'
get 'last_name' do
InlineDB[:directory].sort_by("last_name")
end
end
end

Class like Struct

I have task here: I must create a class which will be like class Struct. I have just started to learn Ruby and don't know how to create it. In my attempts, I was able to create a method that takes arguments and creates an array. Then I have to go through the array and all of the arguments, make the argument class, in which I can bring some value. But I don't know how to create methods that can create classes in Ruby.
I am asking for help if you have an example or know where to find it, I will be grateful!
my attempts:
class Hobbit
def new(*params)
"#{params.inspect}"
end
end
So I assume all you want is
And what i want it is an example of a method that can create classes
Check out this question and the accepted answer which shows you how to create a class dynamically given a class name. Let me know if that's what you're looking for.

Where and how should I add this new 'non-rails-way' method in my Rails application

I've written a small method to query and retrieve from an MS SQL 2008 server and I am not sure where to put the code in my rails app.
The scenario:
I am writing a Ruby and Rails app with a connection to a legacy MS SQL 2008 server DB.
A lot is working as expected, which is nice.
For now I work off a copy of the legacy DB and I treat it as readonly. It's big (7000+ tables some of which have over 40 million records). I am using it 'as-is' and don't want to change any of the underlying schema.
I do want to extend some very server-specific functionality. For instance, I make use of:
thing = ActiveRecord::Base.connection.exec_query(my_query_string_here)
... and it works. The result is an array that contains a hash and I can get to the relevant hash value by using:
thing[0][""]
... which works.
So, I thought I should write a method to make this easier and I wrote:
Class Tool < ActiveRecord::Base
def self.queryRDW(x)
res=ActiveRecord::Base.connection.exec_query(x)
ret=res.to_hash
return ret[0][""]
end
end
and put it in config/initializers/tool.rb Unfortunately, webrick complains about the file during boot with the following cryptic error:
.../config/initializers/tool.rb:7: syntax error, unexpected keyword_end, expecting $end (SyntaxError)
I recognize that this is not an out-of-the-box rails-way of doing things, so please don't remind me. (My struggles remind me often enough)
My question:
Where should I put this code so that I can invoke it from within a controller or a view in my rails app? Does this need to be a new Class method or something else?
Many thanks!
Addendum:
I changed Class to class (doh!)
I moved tool.rb into lib/
I changed tool.rb to now be:
module Tool
def self.queryRDW(x)
res = ActiveRecord::Base.connection.exec_query(x)
res.to_hash[0][""]
end
end
but doing this in app/views/stats.html.erb
thing=queryRDW("mysql string")
gets me an 'undefined method error'
Addendum 2
I made the directory app/concerns and put tool.rb there.
When I use:
<%=queryRDW("myStringHere")%>
in:
app/views/stats.html.erb
I get:
undefined method `queryRDW' for #<#<Class:0x0000000378ccf8>:0x00000003c1ce58>
You need to lowercase the keyword class in line 1.
I'd also say that this class doesn't need to inherit from ActiveRecord::Base — and doesn't even really need to be a class — if it's simply a wrapper around exec_query. There's nothing "wrong" with this, but if you never intend to instantiate an object of this class, you could just create a simple utility module:
module Tool
def self.queryRDW(x)
res = ActiveRecord::Base.connection.exec_query(x)
res.to_hash[0][""]
end
end
You can save this file in a couple of places:
lib/tool.rb. If you're using Rails 3, you'll need to add (or uncomment) this line in config/application.rb:
# config/application.rb
config.autoload_paths += %W(#{config.root}/lib)
app/concerns/tool.rb. This will automatically be detected by Rails 3.
I generally use app/concerns for tools that are entirely application-specific and lib for utilities that I might reuse among several different applications.
I wouldn't put this in config/initializers. This seems like code you'd put in app/models.
The error you're getting is syntax related, so double check the syntax.
To answer your question more directly, though, it's acceptable to put this stuff in your model if it's model related (in other words, part of your business domain). If it is something extraneous or orthogonal to your domain, I'd put it in lib.
Hope this helps.

Accessing a Rails model name from within a lib file of the same method

This may seem like a silly question but I have a model named Ad and I have a library name auto which contains a class Ad(lib/auto.rb).
#auto.rb lib file
module auto
class Ad
def initialize
...
end
def convert
# here I would like to access my model class Ad
# ::Ad does not work. Requiring it does not work either.
end
end
end
Does Rails 3 store models under some global namespace?
Am I missing something or you are defining auto::Ad?
If so, then ::Ad will never work. use auto::Ad or Ad (from within the auto module).
If you really don't want the auto namespace . Remvoe the module auto part in your code.
I think that you can't get it straight from your external class. But you can pass it from your exact model.
I think this can be useful
http://guides.rubyonrails.org/plugins.html#add-an-acts_as-method-to-active-record

Resources