5
\$\begingroup\$

I'm currently working on building a simple REST API using Ruby on Rails. I noticed that a lot of the things I did were a bit redundant, especially the models. Just to clarify: I want this to be a REST API which returns JSON, without any views (I want to be able to access it from different applications, mainly Apache Cordova). Within Cordova I wanted to use ReactJS.

Sadly, my Rails controllers all look like this:

class StudentsController < ApplicationController
 def index
 @students = Student.all
 render json: @students
 end
 def create
 if @student.present?
 render nothing: true, status: :conflict
 else
 @student = Student.new(student_params)
 if @student.save
 render json: @student
 else
 render nothing: true, status: :bad_request
 end
 end
 end
 def show
 @student = Student.find(params[:id])
 render json: @student.classes
 end
 def update
 @student = Student.find(params[:id])
 @student.update(student_params)
 if @student.save
 render json: @student
 else
 render nothing: true, status: :bad_request
 end
 end
 def delete
 if Student.destroy(params[:id])
 render nothing: true, status: :ok
 else
 render nothing: true, status: :bad_request
 end
 end
 private
 def student_params
 params.permit(:first_name, :last_name, :grade_id)
 end
end

I literally got three of them with only the classname changed. Is there a smarter way to organize this? I may have to change override some functions, but some functions will be identical.

I also have a few database relationships, for example grades and classes to teachers and students. Does anyone have some information about best practices for this? I seem to be creating a lot of "relationship" tables for these many-to-many relationships.

For the RoR Rest API Part I found this tutorial.

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Mar 20, 2016 at 16:09
\$\endgroup\$
2
  • \$\begingroup\$ There's nothing wrong with your controller. It's a basic bare bones controller and there's nothing you can do to improve it. If you need some feedback on your models you'll need to post them up. \$\endgroup\$ Commented Mar 25, 2016 at 1:38
  • \$\begingroup\$ There's nothing in my models except the logic for the database yet. I did find out a better way to do controllers. The problem was that I had to write the same code with different classnames for every model, but the tutorial I posted fixed this. \$\endgroup\$ Commented Mar 25, 2016 at 12:10

1 Answer 1

2
\$\begingroup\$

I think this is an interesting idea, although I haven't personally used it when building REST APIs.

Here's some code which shows how it could be done.

I tested the following code to ensure that it works. To test it:

  1. make a todo model with a :name column
  2. add resources :todos to the routes
  3. visit localhost:3000/todos

...

# app/controllers/todos_controller.rb
class TodosController < ApplicationController
 include GenericController
 RecordClass = Todo
 def record_params
 params.require(:todo).permit(:name)
 end
end

You can see that there are only two points of customization in each controller. You'll have to specify the RecordClass and your secure parameters method.

The following "generic controller" was built using Rails' default scaffold controller. You can customize it to follow your own default controller logic.

# app/controllers/generic_controller.rb
module GenericController
 before_action :set_instance, only: [:show, :edit, :update, :destroy]
 def index
 @records = RecordClass.all
 end
 def show
 end
 def new
 @record = RecordClass.new
 end
 def edit
 end
 def create
 @record = RecordClass.new(record_params)
 respond_to do |format|
 if @record.save
 format.html { redirect_to @record, notice: '#{RecordClass} was successfully created.' }
 format.json { render :show, status: :created, location: @record }
 else
 format.html { render :new }
 format.json { render json: @record.errors, status: :unprocessable_entity }
 end
 end
 end
 def update
 respond_to do |format|
 if @record.update(record_params)
 format.html { redirect_to @record, notice: '#{RecordC;ass} was successfully updated.' }
 format.json { render :show, status: :ok, location: @record }
 else
 format.html { render :edit }
 format.json { render json: @record.errors, status: :unprocessable_entity }
 end
 end
 end
 def destroy
 @record.destroy
 respond_to do |format|
 format.html { redirect_to records_url, notice: #{'RecordClass} was successfully destroyed.' }
 format.json { head :no_content }
 end
 end
 private
 def set_record
 @record = RecordClass.find(params[:id])
 end
answered Mar 27, 2016 at 23:13
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.