Had a little fun with acts_like_list... Build in Rails 3, should work in
Rails 4 though???
Add to your gem file:
gem 'acts_as_list'
Run:
bundle install
Add the field position as an integer to your Articles table:
>From rails console:
RUN: rails g migration AddPositionToArticle position:integer
RUN: rake db:migrate
You could go to your database to verify
mysql> describe articles;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| article | varchar(255) | YES | | NULL | |
| rank | int(11) | YES | | NULL | |
| position | int(11) | YES | | NULL | |
+------------+--------------+------+-----+---------+----------------+
Go to your Article model:
class Article < ActiveRecord::Base
attr_accessible :article, :rank, :position
acts_as_list
before_save :position_to_rank
## Just populating rank .... eventually you can delete it, at view level
you can use the work Rank if you are more comfortable with that
def position_to_rank
self.rank = self.position
end
end
Your Articles controller:
class ArticlesController < ApplicationController
def index
@articles = Article.order("position")
end
def rank
@art = Article.find(params[:id])
process = params[:process]
if process == "Move Up"
@art.move_higher
elsif process == "Move Down"
@art.move_lower
elsif process == "Move Bottom"
@art.move_to_bottom
elsif process == "Move Top"
@art.move_to_top
elsif process == "Insert At"
@art.insert_at(params[:id].to_i - 1)
end
redirect_to :action => :index
end
def show
@article = Article.find(params[:id]) unless params[:id].blank?
end
def new
@article = Article.new
end
def create
## Didn't test this, obviously no error management
@article = Article.new(params[:article]) unless params[:article].blank?
if @article.save
redirect_to @article, :notice => "Successfully created article."
else
render :action => 'new'
end
end
def edit
## Didn't test this, obviously no error management
@article = Article.find(params[:id]) unless params[:id].blank?
end
def update
## Didn't test this, obviously no error management
@article = Article.find(params[:id]) unless params[:id].blank?
if @article.update_attributes(params[:article])
redirect_to @article, :notice => "Successfully updated article."
else
render :action => 'edit'
end
end
def destroy
## Didn't test this, obviously no error management
@article = Article.find(params[:id]) unless params[:id].blank?
@article.destroy
redirect_to articles_url, :notice => "Successfully destroyed article."
end
end
Go to your router and verify or add:
resources :articles
match 'articles/rank/(:id)/(:process)' => "articles#rank", :as =>
:articles_rank
Your views in article(s) folder:
index.html.erb
<% "Articles" %>
<table >
<% for article in @articles %>
<tr>
<%= content_tag_for :td, article do %> ## Probably not necessary
<td> <%= link_to "Move Up", articles_rank_url(article.id, "Move Up")
%></td>
<td> <%= link_to "Move Down", articles_rank_url(article.id, "Move
Down") %></td>
<td> <%= link_to "Move Top", articles_rank_url(article.id, "Move Top")
%> </td>
<td> <%= link_to "Move Bottom", articles_rank_url(article.id, "Move
Bottom") %></td>
<td> <%= link_to article.id.to_i, articles_rank_url(article.id,
"Insert At") %></td>
<td> <%= article.article %></td>
<td> <%= "Position " + article.position.to_s %> </td>
<td> <%= "Rank " + article.rank.to_s %> </td>
<td> <%= link_to "Show", article %></td>
<td> <%= link_to "Edit", edit_article_url(article.id) %> </td>
<td> <%= link_to "Destroy", article, {:confirm => 'Are you sure?',
:method => :delete} %></td>
<% end %>
</tr>
<% end %>
</table>
<p><%= link_to "New Article", new_article_path, {:class=>"search"} %></p>
edit.html.erb
<%= "Edit Article" %>
<%= render 'form' %>
<p>
<%= link_to "Show", @article %> |
<%= link_to "View All", articles_path %>
</p>
_form.html.erb
<%= form_for @article do |f| %>
<% if @article.errors.any? %>
<% end %>
<p>
<%= f.label :article %><br />
<%= f.text_field :article %>
</p>
<p><%= f.submit %></p>
<% end %>
new.html.erb
<%= "New Article" %>
<%= render 'form' %>
<p><%= link_to "Back to List", articles_path %></p>
show.html.erb
<%= "Article" %>
<p>
<strong>Article:</strong>
<%= @article.article %>
</p>
<p>
<strong>postion:</strong>
<%= @article.position %>
</p>
<p>
<%= link_to "Edit", edit_article_path(@article) %> |
<%= link_to "Destroy", @article, {:confirm => 'Are you sure?', :method =>
:delete} %> |
<%= link_to "View All", articles_path %>
</p>
That's about it! Hope it works for you!
The api (rails 4) source is : https://github.com/swanandp/acts_as_list
On Sunday, June 28, 2015 at 2:51:57 PM UTC-4, Federicko wrote:
>
> Hi All,
>
> I am learning rails at the moment and have gone through one of the
> tutorials on the rails website for creating a simple blog system.
> I have added some new features to it and it is working great.
> However, I would like to show someone my code and see if it is the right
> or most efficient way of achieve this.
>
> This system is based on the blog system from the Getting Started with
> Rails guide which can be found on
> http://guides.rubyonrails.org/getting_started.html
>
> I simply added a rank up/rank down function to the blog system:
>
> First, in my routes.rb I added:
>
> resources :articles do
> resources :comments
> member do
> get 'rankup'
> get 'rankdown'
> end
> end
>
> Then, in my controller I added two new actions:
>
> def rankup
> @this_article = Article.find(params[:id])
> @new_rank = @this_article.rank.to_i-1
> @prev_article = Article.find_by(rank: @new_rank)
>
> @prev_article.rank = @this_article.rank
> @this_article.rank = @new_rank
>
> @this_article.save
> @prev_article.save
> redirect_to articles_path
> end
>
> def rankdown
> @this_article = Article.find(params[:id])
> @new_rank = @this_article.rank.to_i+1
> @next_article = Article.find_by(rank: @new_rank)
>
> @next_article.rank = @this_article.rank
> @this_article.rank = @new_rank
>
> @this_article.save
> @next_article.save
> redirect_to articles_path
> end
>
> I also updated the destroy action to include a re ranking function:
>
> def destroy
> @article = Article.find(params[:id])
> @start_rank = @article.rank
> @next_articles = Article.where(["rank > ?", @start_rank]).order('rank
> ASC')
>
> @next_articles.each do |article|
> article.rank = @start_rank
> article.save
>
> @start_rank = @start_rank + 1
> end
>
> @article.destroy
> redirect_to articles_path
> end
>
> And in the view I simply added the links to the list:
>
> <% @articles.each.with_index do |article, index| %>
> <tr>
> <td><%= article.title %></td>
> <td><%= article.text %></td>
> <td><%= article.rank %></td>
> <td><%= link_to 'View', article_path(article) %></td>
> <td><%= link_to 'Edit', edit_article_path(article) %></td>
> <td><%= link_to 'Delete', article_path(article), method: :delete,
> data: {confirm: 'Are you sure?'} %></td>
> <td>
> <% if index != 0 %>
> <%= link_to 'Up', rankup_article_path(article) %>
> <% end %>
> </td>
> <td>
> <% if index != @articles.count-1 %>
> <%= link_to 'Down', rankdown_article_path(article) %>
> <% end %>
> </td>
> </tr>
> <% end %>
>
> As mentioned, I am new to RoR so I don't know if I'm doing this correctly
> according the Rails convention but the code is working great so I'm happy
> about that.
>
> If someone can review my code please and tell me what I can improve on,
> that would be great.
>
> I'm also thinking there might be an existing gem or something that I can
> install that will do the ranking for me automatically.
>
> Anyway, look forward to your feedbacks.
>
>
> Thanks in advance.
>
--
You received this message because you are subscribed to the Google Groups "Ruby
on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/rubyonrails-talk/2b45d407-ff12-4d71-b65b-534b6a1ba838%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.