Today I wanted to get how do the rails db:drop works. How did I thought: rails is a name of executive file that executed by Linux system when I type rails db:drop and db:drop is an argument for this file.
This file could be created in different languages, it even could be a binary. But I suppose it is created by a Ruby. So I went to the rails repo. And start reading the code of rails.gemspec but did not find any hints about how do the system parses cli requests.
As I suppose the parsing of rails arguments is work of the rake. But where is the code that points that rake should be started when we call rails?
And what is the brief structure of rails execution?
There must be a rails file, in some directory that mentioned in the PATH variable. And system seek for this rails file, select appropriate interpreter ans start to execute code in this file. Where is the code that create this rails file, and what is the code of this file itself?
File rails is placed in <your_application_root>/bin/ folder.
bin/rails contains someting like this:
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../config/application', __dir__)
require_relative '../config/boot'
require 'rails/commands'
Although, this ^ might be a little outdated, this is just what I found by quick search as an example. Better you check the file in your own application with your version of rails.
Here is some useful information about rails console utilities:
https://edgeguides.rubyonrails.org/command_line.html
Also, from my experience, it's good to have something like RubyMine IDE for learning Ruby on Rails: https://www.jetbrains.com/ruby/download/
It's not free, but there is a 30-days trial which might be enough for understanding most of the basics of the framework.
The main advantage of this IDE is that it has very good integration with ruby version managers such as RVM, where you can add ruby sources and rails gems to the search indexing and easily navigate to methods/files/constants/etc. definitions right from the code. This is much faster than searching/opening a particular file on GitHub.
How to the rails works from the Linux shell point of view?
"rails" command is a part of the Railties gem
Start rails file that stored at the ruby_instalation_dir/bin. This file is generated by RubyGems from the Railties gemsec file. (https://stackoverflow.com/a/59269405/8574922)
rails file is a Ruby file that calls railaties/rails file
and the railaties/rails file requires rails/cli.rb
Yes rails is an executive file that stores in ruby_destination/bin folder. This is a Ruby file generated by RubyGems.
And this files calls for another Gem called Railties that can be installed in the same bin folder, or in the Gems folder, that can be found by a bundle show --paths command. Here it is this executable file that is called from rails.
So the journey begins from the require "rails/cli" of the Railties.
Related
I am new to Ruby so forgive me if my question is obvious. I would really appreciate a little help here.
I have a project which I use as a library. It has 2 rake tasks which gives me a new file which is stored in a folder in the project. Let's say that this rake task serves as a parser and gives a JSON file.
This project can also be used as a gem. The .rake files are placed in the lib path of the project, so the rake tasks are publicly available.
I would like to call this rake tasks in my ruby code, in a new ROR application and have access to the outputed JSON file.
How I can run a rake tasks from a gem in my ROR application code and how I can have access to a file that is stored in the inner folder of the gem?
Ruby on Rails 4 introduced* the ./bin directory. Inside of ./bin are a few executables: bundle, rails, rake, setup, spring.
My questions are:
What do these executables do? Why do they exist?
When are they invoked?
Can I edit them? Why would I edit them?
I've read the source of these files, and I've tried to Google their purpose, but I can't wrap my head around it. I'm looking for an in-depth explanation.
*I believe many of these files existed before Rails 4, just in different location.
Introduced in Rails 4, the ./bin directory contains your app's "binstubs." Binstubs are wrappers around gem executables, like rails or bundle, which ensures a gem executable is run inside the correct environment for your Rails app.
Binstubs can be used in lieu of bundle exec to run a gem's executable inside your app's environment. For example, instead of typing bundle exec rails scaffold products you can type bin/rails scaffold products. Using binstubs is more flexible than bundle exec, because you don't have to cd to the app's root directory and type bundle exec before everything.
By default, bundle, rails, rake, setup, spring binstubs are created automatically for new rails projects. To make a binstub for a gem executable, just type bundle binstubs name_of_gem_executable. You'll find the new binstub in your ./bin directory.
Some suggest putting ./bin in your shell's search $PATH, so that you don't have to type bin/rails and you can just type rails. This is risky because it depends on ./bin coming before the gem executable's path in $PATH; if you happen to forget this ordering and adjust $PATH such that the gem's executable is found before the binstub wrapper, you could easily invoke the gem's executable -- sans the environmental pretext -- without realizing it.
A bin (short for binary) is nothing more than an application. As you have noticed, these files are ruby files, but they do not have the .rb extension and can be run from your shell just as any shell command, without the need to start any ruby interpreter yourself.
So what do theses programs do? I'm pretty sure you know already what rails rake bundle do.
About spring, it's a gem that keeps your app running in the background (hence its need to be run independently from the app). More infos on their github.
I see no reason to edit these files, but that being said, they're ruby files so you can do whatever you want with them. One example of why you may want editing can be found here.
I personally do put some stuffs in the bin folder. Scripts to connect to remote servers, or ruby scripts I need but that I don't want to run as rake tasks since they're more general than my application.
Im following a rails tutorial, and when im supposed to run the command: 'bin/rails generate model Article'. An error occurs saying that there isnt such a command.
I'm using 'command prompt with ruby on rails' and in the rails project i can find a Bin folder. Am also using windows 7.
Also What is the difference between running only 'rails generate' instead of running 'bin/rails generate'?
Using rails generate is fine if you have no bin stubs (binaries in the root /bin folder of your project). If you do have bin stubs then it's preferred to use them because they may do additional things specific to your project. But even then, it's (probably) fine to just use rails generate still. The other bin stubs may be a little more necessary to use, though (again, if present) because they tend to be shortcuts to e.g. bundle exec rake.
Rails 4.1 ships with bin stubs. That is, when you generate a Rails 4.1 project it generates bin stubs for you. So this is probably why your tutorial mentioned using them -- they're now there by default. But if you're on an older version of Rails that won't help you much.
The big reason Rails 4.1 includes bin stubs is because Rails uses spring by default now. Spring is an application preloader... that makes it so that when you call e.g. bin/rake ... it will load and keep a running rails environment in the background and then, the 2nd time you call bin/rake it will fork from the running environment giving you almost instantaneous response. So this is an example of "additional things specific to your project" that you get from using bin/rake over just rake and bin/rails over just rails.
When I open the Gemfile inside RubyMine I can Ctrl+Click on every one of the gems and RubyMine will take me to the gem's source files. Except 'rails'..
In my current project it's
gem 'rails', '3.2.13.rc2'
And I also can't see rails in the 'External Libraries' section.
Any idea how to solve this?
Rubymine is working fine, that's an 'issue' with Rails itself. Unfortunately, I don't have enough knowledge to say it for sure, but I suppose Rails 3.2.x folder is just a stub. I've tested that in my projects and indeed, project using Rails 3.2.13 have empty rvm rails-3.2.13 dir. I've downgraded it few times and rails-3.1.12 contains a single file rails.rb which just requires `railties-3.2.1/lib' where whole Rails are.
I have also another project using Rails 2.3.5 and there rails-2.3.5 contains Rails files, I have also another one using Rails 4.0.2 (why work with one project if you can work with few? ;)) where rails-4.0.2 dir contains only guides.
So, to answer your question: Rubymine sees empty rails-3.2.13.rc2 dir so it can't show you its source. To look into Rails source open railties-3.2.13.rc2/lib/rails directory.
With the helpful information in #zrl3dx's answer I did the following:
Going to some external library in RubyMine to see where it's looking for source files. In my case it was in
~/.rvm/gems/ruby-2.0.0-p247/gems
Then I copied the railties directory to the rails directory
rmdir rails-3.2.13.rc2
cp -a railties-3.2.13.rc2 rails-3.2.13.rc2
Then RubyMine automatically detected the source code and I can happily Ctrl+Click once again :)
I am invoking a shell script using Kernel.system from my Rails controller. The shell script might invoke another Ruby script based on some conditions. This Ruby script requires the twitter gem. My Rails app is running in apache using Passenger. Now when this Ruby script is invoked from my Rails app, I get the following error in apache logs.
/var/www/webapps/test/twitter/twitter_post.rb:2:in `require': no such file to load -- twitter (LoadError)
from /var/www/webapps/test/twitter/twitter_post.rb:2
The same Ruby script runs fine from the Linux shell. Now, if I list the twitter gem in my Gemfile, it works perfectly. Kernel.system is supposed to invoke the commands in a subshell, so is Rails modifying any environment variables in its execution shell?
A subshell has the same environment as the process that spawned it, so the right thing is occurring here, since Bundler overwrites Ruby's load path with its own to ensure only the gems in the Gemfile get loaded.
If your app depends on this process running, and that process depends on the twitter gem, why is it not in your Gemfile anyway? Further, why are you executing Ruby in a subshell from Ruby in the first place? There's usually no reason you shouldn't just have that Ruby code within your app.
you should not be making a system call to another ruby script, you should require or include the contents of the other ruby script.
That being said, your current rubygems environment when you invoke the rails server will be that of the rails application's bundle. If the rails application's bundle does not include the gems that your other ruby script requires, then your other ruby script will not be able to require that library.
So, add to your rails app's Gemfile the the library that the other script is complaining it is missing and I think that should do ya.
In your external ruby script try:
require 'bundler/setup'
taken from bundler setup docs