I'm using Rails 4.0.0 and CKEDITOR to build out a small blog for a client, and I'm having an issue with the page that displays the ten most recent posts and a small excerpt.
If an image was inserted into the post, or a table, or any other html element, that is coming over as well.
Can I just grab the text, without image, tables, etc?
Here is my controller code:
class PostsController < ApplicationController
before_filter :authorize, only: [:new, :create, :edit, :update]
def index
#posts = Post.all
end
def new
#post = Post.new
end
def create
#post = Post.new(params[:post].permit(:title, :text, :photo))
if #post.save
redirect_to #post
else
render 'new'
end
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update(params[:post].permit(:title, :text, :photo))
redirect_to #post
else
render 'edit'
end
end
def destroy
Post.find(params[:id]).destroy
redirect_to posts_path
end
def show
#post = Post.find(params[:id])
end
private
def post_params
params.require(:post).permit(:title, :text, :photo)
end
end
And my view code:
<% #body_class = "blog" %>
<div class="wrap">
<h1>Listing posts</h1>
<p><%= link_to 'New post', new_post_path, 'data-no-turbolink' => 'false' %></p>
<% #posts.each do |post| %>
<div class="post" id="<%= post.id %>">
<div class="postTitle">
<%= post.title %>
</div>
<div class="postContent">
<%= post.text.html_safe %><br/><br/>
<%= link_to 'Show', post_path(post) %>
<% if current_user %>|
<%= link_to 'Edit', edit_post_path(post), 'data-no-turbolink' => 'false' %> |
<%= link_to 'Destroy', post_path(post), :confirm => 'Are you sure you want to delete this post?', :method => :delete %>
<% end %>
</div>
</div>
<% end %>
</div>
Thanks all!
My last resort will be to just create a new column in the database for an "Excerpt that they can write themselves. That may be a better idea anyways.
You need strip_tags plus truncate
truncate(strip_tags(post.text), length: 100, separator: ' ')
And you should save the result in before_save callback into special field you talked about for optimization.
Related
I'm building an Event app using Rails and have comments as a nested resource. I'm trying to implement an Edit function using Ajax/in-line editing but my Edit link isn't working.
I'm not getting an error up on screen but I am getting above error from my development log. The comment 'id' = 27 relates to the event_id not the comment id. How do I rectify this?
Here's the relevant code -
comments_controller.rb
class CommentsController < ApplicationController
before_action :set_event, only: [:show, :create, :edit, :update, :destroy]
before_action :set_comment, only: [:show, :create, :edit, :update, :destroy]
def create
#comment = #event.comments.create(comment_params)
#comment.user_id = current_user.id
if #comment.save
redirect_to #event
else
render 'new'
end
end
# GET /comments/1/edit
def edit
respond_to do |f|
f.js
f.html
end
end
def show
end
def update
if #comment.update(comment_params)
redirect_to #event, notice: "Comment was successfully updated!"
else
render 'edit'
end
end
def destroy
#comment.destroy
redirect_to event_path(#event)
end
private
def set_comment
#comment = Comment.find(params[:id])
end
def set_event
#event = Event.find(params[:event_id])
end
def comment_params
params.require(:comment).permit(:name, :body)
end
end
_comment.html.erb
<div class="comment clearfix">
<div class="comment_content">
<div id="<%=dom_id(comment)%>" class="comment">
<p class="comment_name"><strong><%= comment.name %></strong></p>
<p class="comment_body"><%= comment.body %></p>
</div>
<% if user_signed_in? %>
<p><%= link_to 'Edit', edit_event_comment_path(#event, #comment.event), id: "comment", remote: true %></p>
<p><%= link_to 'Delete', [#comment.event, comment],
method: :delete,
class: "button",
data: { confirm: 'Are you sure?' } %></p>
<% end %>
</div>
</div>
edit.js.erb
$('#comment').append('<%= j render 'form' %>');
_form.html.erb
<%= simple_form_for([#event, #comment], remote: true) do |f| %>
<%= f.label :comment %><br>
<%= f.text_area :body %><br>
<br>
<%= f.button :submit, label: 'Add Comment', class: "btn btn-primary" %>
<% end %>
I've checked the routes and they're all as they should be.I can't check whether the in-line editing will work unless I fix this first.
As far as I can see you have two before actions, set_event and then set_comment.
If you've set both of these to look for params[:id], then it means they will obviously both be using the same value for a search. You will need to change one of them, let us say set_event, to something like:
def set_event
#event = Event.find(params[:event_id])
end
You will also have to change your routes to account for the new id. If you are using your standard resource routes:
resources :events, param: event_id do
resources :comments
end
This will give you routes such as:
localhost:3000/events/:event_id/comments/:id
Which you can then use to find your events and comments.
screenshot
Currently I'm using acts_as_votable gem along with bootstrp-sass gem,I want to upvote the post when glyphicon icon is clicked, instead it throws me above errors.
This is my posts_controller.rb file
class PostsController < ApplicationController
before_action :authenticate_user!, except: [:index, :show]
def search
if params[:search].present?
#posts = Post.search(params[:search])
else
#posts = Post.all
end
end
def index
#posts = Post.all.order('created_at DESC')
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
if #post.save
redirect_to #post
else
render 'new'
end
end
def show
#post = Post.find(params[:id])
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update(params[:post].permit(:title, :date, :time, :location))
redirect_to #post
else
render 'edit'
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
redirect_to root_path
end
def upvote
#post.upvote_by current_user
redirect_to :back
end
private
def post_params
params.require(:post).permit(:title, :date, :time, :location)
end
end
This is my show.html.erb file
<div id="post_content">
<h1 class="title">
<%= #post.title %>
</h1>
<p class="date">
Submitted <%= time_ago_in_words(#post.created_at) %> Ago
<% if user_signed_in? %>
| <%= link_to 'Edit', edit_post_path(#post) %>
| <%= link_to 'Delete', post_path(#post), method: :delete, data: { confirm: 'Are you sure?' } %>
<% end %>
</p>
<p class="date">
<%= #post.date %>
</p>
<p class="time">
<%= #post.time %>
</p>
<p class="location">
<%= #post.location %>
</p>
<div id="comments">
<div class="btn-group pull-left">
<%= link_to like_post_path(#post), method: :put, class: "btn btn-default" do %>
<span class="glyphicon glyphicon-heart"></span>
<%= #post.get_upvotes.size %>
<% end %>
</div>
<h2><%= #post.comments.count %> Comments</h2>
<%= render #post.comments %>
<h3>Add a comment:</h3>
<%= render "comments/form" %>
</div>
This is my routes.rb file
Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
devise_for :users
resources :posts do
resources :comments
collection do
get 'search'
end
member do
put "like", to: "posts#upvote"
end
end
root "posts#index"
get '/about', to: 'pages#about'
end
And this is my post model
class Post < ActiveRecord::Base
acts_as_votable
searchkick
has_many :comments, dependent: :destroy
validates :title, presence: true, length: {minimum: 5}
validates :date, :time, :location, presence: true
belongs_to :user
end
NoMethodError in PostsController#upvote undefined method `upvote_by'
for nil:NilClass
The error is because you didn't initialized #post in upvote method so #post is nil
def upvote
#post = Post.find(params[:id])
#post.upvote_by current_user
redirect_to :back
end
I'm new to rails, I have followed the Blogger tutorial from Jumpstart Labs to make a blogging app, and I am trying to implement a feature that will allow users who are logged in to delete comments on articles.
but I keep getting confused by this error message "ActiveRecord::RecordNotFound in CommentsController#destroy
Couldn't find Article with 'id'="
here's what I've managed so far,
this is my app/controllers/comments_controller.rb
class CommentsController < ApplicationController
before_filter :require_login, except: [:create]
def create
#comment = Comment.new(comment_params)
#comment.article_id = params[:article_id]
#comment.save
redirect_to article_path(#comment.article)
end
def destroy
#article = Article.find(params[:article_id])
#comment = #article.comments.find(params[:id])
#comment.destroy
redirect_to article_path(#article)
end
private
def comment_params
params.require(:comment).permit(:author_name, :body)
end
end
and my /views/articles/show.html.erb
<h1><%= #article.title %></h1>
<p>
<b>Posted on <%= #article.created_at.strftime("%B %d %Y") %></b>
</p>
<p>
<% if #article.image.exists? %>
<%= image_tag #article.image.url%>
<% end %>
</p>
<p><%= #article.body %></p>
<%= render partial: 'comments/form' %>
<% if logged_in? %>
<%= link_to "Edit", edit_article_path(#article) %>
<%= link_to "delete", article_path(#article), method: :delete%>
<% end %>
<%= link_to "<< Back to Articles List", articles_path %>
<h3>Comments (<%=#article.comments.size %>) </h3>
<%= render partial: 'articles/comment',
collection: #article.comments %>
<p>
Tags:
<% #article.tags.each do |tag| %>
<%= link_to tag.name, tag_path(tag) %>
<% end %>
</p>
app/views/articles/comment.html.erb
<div>
<p><b>Comment by:</b> <%= comment.author_name %></p>
<p class="comment"><%= comment.body %></p>
<p>Posted <%= distance_of_time_in_words(comment.article.created_at, comment.created_at) %> later</p>
<%= link_to 'Delete Comment', article_comment(article, comment), method: :delete, data: { confirm: 'Are you sure?' } %>
</div>
routes.rb
Blogger::Application.routes.draw do
get 'about', to: 'info#about'
get 'portfolio', to: 'info#portfolio'
get 'contact', to: 'info#contact'
root to: 'articles#index'
resources :articles do
resources :comments
end
resources :tags
resources :authors
resources :author_sessions, only: [ :new, :create, :destroy ]
get 'login' => 'author_sessions#new'
get 'logout' => 'author_sessions#destroy'
end
and my articles_controller
class ArticlesController < ApplicationController
include ArticlesHelper
before_filter :require_login, only: [:new, :create, :edit, :update, :destroy]
def index
#articles = Article.all
end
def new
#article = Article.new
end
def create
#article = Article.new(article_params)
#article.save
flash.notice = "Article '#{#article.title}' Created!"
redirect_to article_path(#article)
end
def show
#article = Article.find(params[:id])
#comment = Comment.new
#comment.article_id = #article.id
end
def edit
#article = Article.find(params[:id])
end
def update
#article = Article.find(params[:id])
#article.update(article_params)
flash.notice = "Article '#{#article.title}' Updated!"
redirect_to article_path(#article)
end
def destroy
#article = Article.find(params[:id])
#article.destroy
flash.notice = "Article '#{#article.title}' Deleted!"
redirect_to articles_path
end
end
Any input or advice greatly appreciated, I've been looking around google and stack overflow for a while but I haven't found a solution yet
The error NameError in Articles#show undefined local variable or method article can be fixed by changing this line in app/views/articles/_comment.html.erb (I believe it has _)
from
<%= link_to 'Delete Comment', article_comment(article, comment), method: :delete, data: { confirm: 'Are you sure?' } %>
to
<%= link_to 'Delete Comment', article_comment_path(comment.article, comment), method: :delete, data: { confirm: 'Are you sure?' } %>
And in views/articles/show.html.erb, try to change collection: #article.comments to collection: #article.comments.all.
To get past that particular error your having you need to permit the :id and :article_id params
Add them like this
params.require(:comment).permit(:author_name, :body, :id, :article_id)
Following railcasts tutorial on ransack, I was able to create search engine on my Post page. However, I want to implement those same search engine on my Welcome#index (main) page. I have tried in the same way, but whenever I click search, it returns to the welcome#index page instead of searched post page :( I am new to ruby on rails:(
This is my post controller:
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy, :vote]
skip_before_filter :verify_authenticity_token, :only => [:edit, :update, :destroy, :vote]
# GET /posts
# GET /posts.json
def index
#search = Post.search(params[:q])
#posts = #search.result
#posts = #search.result(:distinct => true)
#search.build_sort if #search.sorts.empty?
respond_to do |format|
format.html
format.json{ render json: #posts}
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:area, :price, :people, :size, :description, :image)
end
end
posts index.html.erb:
<%= search_form_for #search do |f| %>
<div class="field">
<h1>Search</h1>
<%= f.label :area_cont, "area" %>
<%= f.text_field :area_cont, class: "area_search"%>
</div>
<div class="post_actions">
<%= f.submit "Search", class: "btn btn-warning" %>
<%= link_to "Clear Search", request.path, class: "btn btn-primary" %>
</div>
<% end %>
welcome#index
<p>
<form class="navbar-search pull-left">
<%= search_form_for #search do |f| %>
<div class="field">
<h1>Search</h1>
<%= f.label :area_cont, "area" %>
<%= f.text_field :area_cont, class: "area_search"%>
</div>
<div class="post_actions">
<%= f.submit %>
<%= link_to "Clear Search", request.path, class: "btn btn-primary" %>
</div>
<% end %>
</form>
</p>
Welcome controller
class WelcomeController < ApplicationController
def index
#search = Post.search(params[:q])
#posts = #search.result
#posts = #search.result(:distinct => true)
#search.build_sort if #search.sorts.empty?
respond_to do |format|
format.html
format.json{ render json: #posts}
end
end
end
I just uploaded parts that would be relevant to this question :( please let me know if other part of code is necessary!! Thank you!
This is my welcome#index.html.erb:
and I have erased contents in welcome controller
<div id="headerwrap">
<div class="container">
<div class="row centered">
<div class="col-lg-8 col-lg-offset-2">
<h1>search</b></h1>
<p>
<form class="navbar-search pull-left">
<%= form_tag("/posts", method: "GET") do %>
<%= label_tag(:q, "Search for:") %>
<%= text_field_tag(:q) %>
<%= submit_tag("Search") %>
<% end %>
</form>
</p>
</div>
</div><!-- row -->
</div><!-- container -->
</div><!-- headerwrap -->
After running bundle exec
welcome#index keeps rendering for you, because you never tell Rrails not to do that when there is a search result.
So the WelcomeController snippet you shared should look like this:
class WelcomeController < ApplicationController
def index
#search = Post.search(params[:q])
#posts = #search.result
#posts = #search.result(:distinct => true)
#search.build_sort if #search.sorts.empty?
if #posts.count > 0
# If we have any matches, render the posts/index view.
render 'posts/index'
else
respond_to do |format|
format.html
format.json{ render json: #posts}
end
end
end
end
This is still a partial solution, because you have to take care of the case when the user enters a search string but there is no result, but this will get you started.
Based on your PostsController code.
You can try this.
The form in your welcome#index.html.erb, should have contained q param
For example,
<%= form_tag(search_posts_path, method: "GET") do %>
<%= label_tag(:q, "Search for:") %>
<%= text_field_tag(:q) %>
<%= submit_tag("Search") %>
<% end %>
And your Welcome Controller index action, can be empty. Because the form search through post controller index action.
class WelcomeController < ApplicationController
def index
end
end
There are other ways to handle this like making a posts controller index to be a root (or you would call a main page) then invoke search method when there is a search param, pass the q param to welcome index action then redirect the param to post action etc.
This is error I'm getting when I click on "New Post:
First argument in form cannot contain nil or be empty
My PostController:
class PostsController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
def index
#posts = Post.all
end
def show
end
def edit
end
def update
#post.update(post_params)
redirect_to posts_path
end
def new
if user_signed_in?
#post = Post.new
else
flash[:alert] = ":("
end
end
def create
#post = Post.new(post_params)
#post.user_id = current_user.id
#post.save
redirect_to posts_path
end
def destroy
if user_signed_in?
#post.destroy!
else
flash[:alert] = ":("
end
redirect_to posts_path
end
private
def post_params
params.require(:post).permit(:body)
end
def set_user
#post = Post.find(params[:id])
end
end
and posts#index:
<% #posts.each do |post| %>
<%= post.body %>
<%= link_to 'Show', post %>
<%= link_to 'Edit', edit_post_path(post) %>
<%= link_to 'Delete', post, method: :delete %>
<br>
_form.html.erb
<%= form_for(#post) do |f| %>
<div class="field">
<%= f.label :body %><br>
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
you should check your "new.html.erb" or "_form.html.erb" file. to see if the "form_for" method is correctly called.
If you are using devise, You can get this by adding a before action:
before_action :authenticate_user!, only: [:new]
and you new action as:
def new
#post = Post.new
end