patternrubyrailsMinor
Rails guestbook with new, index, and Kaminari pagination in the same method
Viewed 0 times
paginationsamethenewmethodwithguestbookrailskaminariand
Problem
I created a guestbook that on one page displays both the form for a new entry and all of the entries that have been created so far.
I am trying to use Kaminari for pagination for the entries.
Right now this code is working on my local machine, but I just have that feeling that it could be improved/refactored, so I wanted to post it here for people's opinions.
My controller:
Routes:
Now I know my routes file could look like this
but then my paths look strange:
I am trying to use Kaminari for pagination for the entries.
Right now this code is working on my local machine, but I just have that feeling that it could be improved/refactored, so I wanted to post it here for people's opinions.
My controller:
class GuestbooksController < ApplicationController
def index
@guestbooks = Guestbook.all
end
def new
@guestbook = Guestbook.new
@guestbooks = Guestbook.all
@guestbooks = Kaminari.paginate_array(@guestbooks).page(params[:page]).per(5)
end
def create
@guestbook = Guestbook.new(guestbook_params)
@guestbooks = Guestbook.all
@guestbooks = Kaminari.paginate_array(@guestbooks).page(params[:page]).per(5)
if @guestbook.save
flash.now[:notice] = "Thanks for taking the time to write us! We greatly appreciate it!"
render :new
else
flash.now[:notice] = "Your message failed to post, please try again"
render :new
end
end
private
def guestbook_params
params.require(:guestbook).permit(:name, :email, :message)
end
endnew.html.erb template:
,
-----------------------------------------------------------------------------------------------------------------------
Routes:
resources :guestbooks, only: [:new, :create]
get "/guestbooks/index", to: "guestbooks#index"Now I know my routes file could look like this
resources :guestbooks, only: [:new, :create, :index]but then my paths look strange:
guestbooks GET /guestbooks(.:format) guestbooks#index
POST /guestbooks(.:format) guestbooks#create
new_guestbook GET /guestbooks/new(.:format) guestbooks#newSolution
Yes, there's a lot that can be done differently.
Firstly, Ruby convention is 2 spaces of indentation. Not 4, not tabs.
Secondly,
Mostly, though I fail to understand the structure of your pages. If you go to
But why is the
I'd cut the controller down to this (keeping, for now, the
No
For your view (which should be the
Also, look into partials, aka partial views. If a partial is properly used, the whole entries list can be rendered as just:
Lastly for the view,
For your routes, you only need this:
The paths in your question do not look strange: Two of them are both called
Firstly, Ruby convention is 2 spaces of indentation. Not 4, not tabs.
Secondly,
Guestbook isn't a great name for your model. You're modelling entries in a guestbook, not multiple guestbooks.Mostly, though I fail to understand the structure of your pages. If you go to
index you load all the entries. If you go to new you... also load all the entries. But then you do some pagination, which, in effect, discards all but 5 of the records you just loaded from the database. Imagine how well that'll work if you have thousands of entries...But why is the
new action listing and paginating anything? That's the job of the index action; to list things, to be an index. Sure, you can combine the two by having a form and a list on the same page, but in that case it should be on the index view.I'd cut the controller down to this (keeping, for now, the
Guestbook model name):class GuestbooksController < ApplicationController
before_action :load_guestbooks
def index
@guestbook = Guestbook.new
end
def create
@guestbook = Guestbook.new(guestbook_params)
if @guestbook.save
redirect_to guestbooks_url, notice: "Thanks for taking the time to write us! We greatly appreciate it!"
else
flash.now[:alert] = "Your message failed to post, please try again"
render :index
end
end
private
def load_page
@guestbooks = Guestbook.page(params[:page])
end
def guestbook_params
params.require(:guestbook).permit(:name, :email, :message)
end
endNo
new action whatsoever. I haven't used kaminari, but just going to its github page I see several examples of usage that are much cleaner than loading everything. The whole point of pagination is not do that.For your view (which should be the
index view), I would read up on class naming, semantics, and HTML in general, I'm sorry to say. For instance, the hr tag could save you a few dozen hyphens, and span1, span2 etc. are not useful names for anything - certainly not divs. And don't use br for layout; use CSS.Also, look into partials, aka partial views. If a partial is properly used, the whole entries list can be rendered as just:
Lastly for the view,
simple_form does not need a url or method argument if they can be derived from the record. Which they can in this case.For your routes, you only need this:
resources :guestbooks, only: [:index, :create]The paths in your question do not look strange: Two of them are both called
guestbooks_path because they do indeed have the same path - but the action they invoke depend on the method (POST or GET) used. If you POST to /guestbooks it'll invoke the create action; if you simply GET /guestbooks, it'll invoke the index action. That's the basic premise of routing in Rails.Code Snippets
class GuestbooksController < ApplicationController
before_action :load_guestbooks
def index
@guestbook = Guestbook.new
end
def create
@guestbook = Guestbook.new(guestbook_params)
if @guestbook.save
redirect_to guestbooks_url, notice: "Thanks for taking the time to write us! We greatly appreciate it!"
else
flash.now[:alert] = "Your message failed to post, please try again"
render :index
end
end
private
def load_page
@guestbooks = Guestbook.page(params[:page])
end
def guestbook_params
params.require(:guestbook).permit(:name, :email, :message)
end
end<%= render @guestbooks %>resources :guestbooks, only: [:index, :create]Context
StackExchange Code Review Q#113087, answer score: 4
Revisions (0)
No revisions yet.