patternrubyrailsMinor
REST API with Ruby on Rails and ReactJS
Viewed 0 times
restreactjswithrailsrubyandapi
Problem
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:
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.
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
endI 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.
Solution
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:
...
You can see that there are only two points of customization in each controller.
You'll have to specify the
The following "generic controller" was built using Rails' default scaffold controller.
You can customize it to follow your own default controller logic.
Here's some code which shows how it could be done.
I tested the following code to ensure that it works. To test it:
- make a todo model with a :name column
- add
resources :todosto the routes
- 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
endYou 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])
endCode Snippets
# app/controllers/todos_controller.rb
class TodosController < ApplicationController
include GenericController
RecordClass = Todo
def record_params
params.require(:todo).permit(:name)
end
end# 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])
endContext
StackExchange Code Review Q#123392, answer score: 2
Revisions (0)
No revisions yet.