For us, ruby/rails developers is very common to start our projects/apps with something very similar to the Rails scaffold….
You know, like…
class PostsController < ApplicationController
def show
@post = Post.find(params[:id])
end
def index
@posts = Post.all
end
#....
end
And in general is hard to find examples of a non-rails way of doing things. Even the basic CRUD…
For example…
Do you know how to build a CRUD without ActiveRecord?
Can you build a CRUD without knowing which database you are going to use? Or which library are you going to use? Can you delay those decisions? Can you make them interchangeable?
If you don’t know how to do it or you have curiosity about how other person would do it… Maybe you can keep reading =)
I want to show you an example of how you can build a simple blog, very similar to what a Rails scaffold can do but without Rails and without a “real database”. I want to show you an example of how you can make those decisions less important…
You can see the app working here and the code here.
The behavior of the app is exposed by stateles module functions in the module
Blog
that lives on lib/blog.rb.
module Blog
def self.list_posts(store)
store.all.sort_by(&:created_at).reverse
end
def self.get_post(id, store)
store.find(id)
end
def self.new_post_form
PostForm.new
end
def self.create_post(params, store, current_time = Time.now)
ProcessPostForm.(params) do |form|
store.create(form.to_h.merge(created_at: current_time))
end
end
def self.edit_post_form(id, store)
PostForm.new(store.find(id))
end
def self.update_post(post_id, params, store)
ProcessPostForm.(params) do |form|
store.update(post_id, form.to_h)
end
end
def self.delete_post(post_id, store)
store.destroy(post_id)
end
#...
end
There is a test file for each CRUD action…
And there is a test file for our “store”…
And the app is exposed using Sinatra… But don’t focus to much on it, that’s not the point… The point is to show you a way of decoupling your business logic from your storage and delivery mechanisms.
store = Blog::Store.new
get "/" do
posts = Blog.list_posts(store)
haml :index, locals: { posts: posts }
end
get "/posts/new" do
form = Blog.new_post_form
haml :new, locals: { form: form }
end
post "/posts" do
status = Blog.create_post(params, store)
if status.success?
redirect to("/")
else
haml :new, locals: { form: status.form }
end
end
get "/posts/:id" do |id|
post = Blog.get_post(id, store)
haml :show, locals: { post: post }
end
get "/posts/:id/edit" do |id|
form = Blog.edit_post_form(id, store)
haml :edit, locals: { form: form, post_id: id }
end
put "/posts/:id" do |id|
status = Blog.update_post(id, params, store)
if status.success?
redirect to("/")
else
haml :edit, locals: { form: status.form, post_id: id }
end
end
delete "/posts/:id" do |id|
Blog.delete_post(id, store)
redirect to("/")
end
I think that is just a different way… But I think that as a developers is actually better for us to know how to solve a problem in different ways to be able pick the best solution on each situation… We need more examples =)
I send an email each week, trying to share knowledge and fixes to common problems and struggles for ruby on rails developers, like How to fetch the latest-N-of-each record or How to test that an specific mail was sent or a Capybara cheatsheet. You can see more examples on Most recent posts or All post by topic.