I'm pretty tired of writing this line every time I want to open the Rails console:
irb(main):001:0> ActsAsTenant.current_tenant = User.find(1).account
Is there any way to run command/script before every "rails c"/"irb" invocation?
Thanks in advance!
Put the code you want to execute into .irbrc file in the root folder of your project:
echo 'ActsAsTenant.current_tenant = User.find(1).account' >> .irbrc
bundle exec rails c # ⇐ the code in .irbrc got executed
Sidenote: Use Pry instead of silly IRB. Try it and you’ll never roll back.
I wrote an extended answer to this in another question but the short answer is that if you are using Rails 3 or above you can use the console method on YourApp::Application to make it happen:
module YourApp
class Application < Rails::Application
...
console do
ActsAsTenant.current_tenant = User.find(1).account
end
end
end
You could put your setup code in a rb file, for example:
foo.rb:
def irb_setup
ActsAsTenant.current_tenant = User.find(1).account
end
launch irb like this:
irb -r ./foo.rb
and call the method (which will autocomplete pressing tab)
2.3.0 :001 > init_irb
In fact maybe you could put the code directly, without any method, and it would be executed when it is loaded. But I'm not sure if that would work or mess with the load order.
Related
I'm new to Ruby on Rails and am trying to access my site's database. I generated and set up a model and controller called Machine, and noticed that in places like the Machine view I could iterate through all the machines in my database simply using #machines.each. However, this doesn't appear to be universal, as when I created a new Ruby file directly in my project's outermost directory, both #machines.each and the attempted assignment #machines = Machine.all threw errors (a NoMethodError and NameError respectively). Here's an example of code I could try to run:
#machines = Machine.all
#machines.each do |machine|
puts machine.created_at
end
Perhaps I need some kind of import statement?
If you are writing a script in plain Ruby -- then yes, you'll have to import everything manually, establish a connection to the DB, etc.
The code would roughly look like this:
require 'active_support'
require 'active_record'
your_db_config = {
# your DB config goes here
}
ActiveSupport::Dependencies.autoload_paths += File.join(__dir__, "app/models")
ActiveRecord::Base.establish_connection(your_db_config)
machines = Machine.all
Consider creating a task if you want Rails to take care of all that and don't want to be doing all that stuff manually.
When you start a rails server (or a rails console) it preloads your Rails application so that your models, constants, etc. are automatically in scope. If you want to access your application's resources from a separate script you still need to load the app. The simplest way to do that is with the rails runner command, which loads your app and then executes a script. So if your script above is in lib/show_machines you'd run:
$ bin/rails runner lib/show_machines
If you like self-executing scripts you can also use runner as a 'shebang' line:
#!/usr/bin/env <your_project_path>/rails/runner
#machines = Machine.all
#machines.each do |machine|
puts machine.created_at
end
Let's say I wanted a greeting every time the Rails console comes up:
Scotts-MBP-4:ucode scott$ rails c
Loading development environment (Rails 4.2.1)
Hello there! I'm a custom greeting
2.1.5 :001 >
Where would I put the puts 'Hello there! I\'m a custom greeting' statement?
Another Stackoverflow answer suggested, and I've read this elsewhere too, that I can put that in an initializer like this:
# config/initializers/console_greeting.rb
if defined?(Rails::Console)
puts 'Hello there! I\'m a custom greeting'
end
That doesn't work for me though :(. Even without the if defined?(Rails::Console) I still don't get output. Seems like initializers are not run when I enter a console, despite what others suggest.
I use ~/.irbrc for similar purposes (I require a gem in each console session). For example, my .irbrc
if (defined? Rails)
# Rails specific
end
# common for all irb sessions
You could use your project name to limit executing code to only one project's console:
if (defined? Rails) && (defined? YourProject)
# code goes here
end
The following will work in Rails 6:
Just pass a block to Rails.application.console, e.g
# config/initializers/custom_console_message.rb
if Rails.env.production?
Rails.application.console do
puts "Custom message here"
end
end
Now when starting the rails production console, the custom message will be printed. This code will not be executed when you start rails server.
Remove the if Rails.env.production? if you want this to run in all environments.
im having a problem using the gem whenever v0.8.4. The config/schedule.rb looks like this:
every :day, :at => '8am' do
runner "TimeclockReportSender.sendReports"
end
The thing is the TimeclockReportSender.sendReports code does not execute. The file is in /vendor/plugins/plugin_name/lib/reports/timeclock_report.rb.
Im developing at a rails 2.3.5 project, using redmine 1.1.1. Any one knows how i can specify the whenever to execute the plugin module code or if i must put this piece of code elsewhere.
UPDATE
module TimeclockReportSender
require "reports/timeclock_report.rb"
#verify and send every report that has date_to_send == today
def self.sendReports
reports = CtTimeclockReport.find(:all)
reports.each do |rpt|
if !rpt.date_to_send.nil?
if rpt.date_to_send.to_date() == Date.today
users = CtTimeclockReport.getAllUsersFromReport(rpt)
period = CtSettingsPeriod.getPeriod(rpt.ct_settings_period_id)
project = Project.find(period.project_id)
pdf = TimeclockReport.createAndGetReport(rpt,project)
sent = TimeclockReportSender.sendReport(rpt,pdf,users)
TimeclockReportSender.updateReportDate(rpt)
end
end
end
end
#send a single report pdf via email to the users list
def self.sendReport(report,pdfReport,users)
#send the report to each user
users.each do |usr|
usr = User.find(usr.user_id)
if !usr.nil?
CtMailer.deliver_reportEmail(report,pdfReport,usr)
end
end
return true
end
when i run the command:
script/runner -e production '\''TimeclockReportSender.sendReports'\''' at rails root, it asks me some input ... this command its the crontab generated from whenever
UPDATE2
To run the sendReports method, i must require the file in my controller using
require "reports/timeclock_report_sender.rb"
FIXED
I ran the cmd from cron and found out that rails was not finding my module. The solution was to put the code inside a Model from my plugin, than it found his code. Thanks 4 all :D
Problem solved! I found out that the reason why it was not executing by running the cmd from cron and then i found out that rails was not finding my module.
The solution was to put the code inside a Model from my plugin, than cron found his code. Thanks for the help guys.
In order to override the table_exists? method in the Rails PostgreSQL adapter I have tried the following in an initializer file:
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do
def table_exists?(name)
raise 'got here'
end
end
This will raise the the following error:
uninitialized constant ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
I believe this would have worked in previous versions of rails and I even found a small plugin that did something like this in Rails 2.3.6. Also I only encounter this error when I am trying to run a rake task like db:migrate and not when I start my application server.
Could someone show me the right way to do this and / or explain why PostgreSQLAdapter doesn't seem to be loaded when I am in an initializer file?
Instead of config/initializers, place that code in lib/ folder.
While this means that the active_record is loaded after the rails initializers, which is unusual. I ll update this with more detail, once I am done investigating the whole flow. If you want some more details about the rails 3 initialization process, check out this link:
http://ryanbigg.com/guides/initialization.html
I had success by moving this code into a Rails plugin. It is a little bit more overhead, but it is working consistently when I run rails s and when I run rake db:migrate.
I just followed the rails guide page on the topic and ran
rails generate plugin rails_patches --with-generator
and moved my init.rb file into rails as recommended.
~vendor/
`~plugins/
`~rails_patches/
|~lib/
| `-rails_patches.rb
|~rails/
| `-init.rb
|+test/
|-install.rb
|-MIT-LICENSE
|-Rakefile
|-README
`-uninstall.rb
I put this code in init.rb:
require 'rails_patches'
I put this code in rails_patches.rb:
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do
def table_exists?(name)
raise 'got here'
end
end
This now behaves as I expected.
I want to run a method, on the startup of the rails server. It's a model method.
I tried using config/initializers/myfile.rb, but the method was invoked during migrations, so it SELECTed from a nonexistant table.
Tried environment.rb also, but the class does not exist yet (and will probably have the same problem with migrations)
I don't know where to put that method, so it'll run only on server startup and not during migrations.
There are some things you could do to actually improve this a bit. The issue is that you are running this code when rake loads your environment, but you really only want to run this when the environment is loaded by an instance of your web server. One way to get around this is to set a value when rake loads your environment, and when that value is set, to not execute your initializer code. You can do this as follows:
task :environment => :disable_initializer
task :disable_initializer do
ENV['DISABLE_INITIALIZER_FROM_RAKE'] = 'true'
end
#In your initializer:
ENV['DISABLE_INITIALIZER_FROM_RAKE'] || MyModel.method_call
There is no way to avoid this from my understanding. You can put the initializer code that relies on the new table in a rescue block to quiet things down so others can run migrations.
Try putting your method call in boot.rb, in the run method after the Rails::initializer call. I don't have rails in front of me right now because I'm at work but I think that the whole environment should be loaded by that point and you can run methods on the framework.
I found this to work quite well:
if File.basename($0) == "rails" && ARGV == []
It also detects "rails generate .."