I am fairly new to Ruby on Rails and as a C# developer, when I want to re-use code (for a repository class), I could put it into a base class of type <T>
to be able to do something like this:
public virtual IEnumerable<T> GetAll()
{
return Context<T>.GetAll();
}
If I need to do any custom logic, I could, of course, override the method in my 'User' repository.
In Ruby, I am familiar that you can do this:
class UsersController < ApplicationController
This will allow access to all methods in ApplicationController and it's parent classes. When using scaffolding, it generates the following method in each of my child classes:
def index
@users = User.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @users }
end
end
What I end up with is 10 classes that have the same method, but the only difference is 'User.all', 'Post.all', etc.
How would I make this method generic so I can put it in my ApplicationController class?
Thanks for any assistance you can provide to a Ruby on Rails newbie.
The first thing to realize about the scaffolding code is that it can be abreviated, as such:
def index
@users = User.all
end
unless you intend to deliver the view in another format, like json, html, pdf, the respond_to block is unnecessary. If you still feel the need to dry up this method, you could do something like
# app/controllers/concerns/autoload_records.rb
module AutoloadRecords
included do
before_action :load_records, only: :index
before_action :load_record, only: [:create, :show, :edit, :update, :destroy]
end
private
def load_records
@records = model_class.all
end
def load_record
@record = model_class.find(params[:id])
end
def model_class
klass = self.class.to_s[/\A(\w+)sController\Z/,1] #=> get the name of the class from the controller Constant
Object.const_get(klass)
end
end
and write your controller like
class UsersController < ApplicationController
include AutoloadRecords
def index
@records # => #<ActiveRecord::Relation[...]>
end
def show
@record # => #<User ...>
end
def non_rest_action
@record # => nil
@records # => nil
end
end
Rather than doing an eval
where you really don't want to be doing one. Check out Jose Valim's Inherited Resources gem. It provides the standard CRUD methods for all of your controllers and is quite sophisticated. It is also thoroughly tested so you don't have to worry about making sure your generic code operates as expected in all cases.
For details on how to use it see the GitHub page linked.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With