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.
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.
I'm trying to include a form partial for the model request in another partial view.
I have a model called request.
class CreateRequests < ActiveRecord::Migration[5.0]
def change
create_table :requests do |t|
t.string :name
t.string :email
t.string :phone
t.string :product
t.string :details
t.timestamps
end
end
end
I have my requests_controller.rb
class RequestsController < ApplicationController
before_action :set_request, only: [:show, :edit, :update, :destroy]
# GET /requests
# GET /requests.json
def index
#requests = Request.all
end
# GET /requests/1
# GET /requests/1.json
def show
end
# GET /requests/new
def new
#request = Request.new
end
# GET /requests/1/edit
def edit
end
# POST /requests
# POST /requests.json
def create
# Create the user from params
#request = Request.new(request_params)
if #email.save
# Deliver the signup email
RequestNotifierMailer.send_email(#request).deliver
flash[:success] = "Thanks! We'll be in touch soon!"
redirect_to :action => 'new'
else
render :action => 'new'
end
end
# PATCH/PUT /requests/1
# PATCH/PUT /requests/1.json
def update
respond_to do |format|
if #request.update(request_params)
format.html { redirect_to #request, notice: 'Request was successfully updated.' }
format.json { render :show, status: :ok, location: #request }
else
format.html { render :edit }
format.json { render json: #request.errors, status: :unprocessable_entity }
end
end
end
# DELETE /requests/1
# DELETE /requests/1.json
def destroy
#request.destroy
respond_to do |format|
format.html { redirect_to requests_url, notice: 'Request was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_request
#request = Request.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def request_params
params.require(:request).permit(:name, :email, :phone, :product, :details)
end
end
The form partial I have requests/_form.html.erb
<%= form_for(request) do |f| %>
<% if request.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(request.errors.count, "error") %> prohibited this request from being saved:</h2>
<ul>
<% request.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :email %>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :phone %>
<%= f.text_field :phone %>
</div>
<div class="field">
<%= f.label :product %>
<%= f.text_field :product %>
</div>
<div class="field">
<%= f.label :details %>
<%= f.text_field :details %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And I included the resource in my config/routes.rb by adding:
resources :requests
I'm trying to include requests/form into static_pages/_requestquote.html.erb:
<div class="actionsHolder">
<div class="buyHolder">
<h2>Starting from <%= price %></h2>
<h3 id="myBtn">
<a href="#">
Request for Quote
</a>
</h3>
</div>
</div>
<div id="myModal" class="modal">
<div class="modal-content">
<span class="close">×</span>
<%= render :partial => "requests/form" %>
</div>
</div>
However I'm getting the error:
NoMethodError in Products#bigmikepopular113
Showing /Users/beckah/Documents/projects/Envirovacs/app/views/requests/_form.html.erb where line #1 raised:
undefined method `model_name' for #<ActionDispatch::Request:0x007fee89b49040>
Extracted source (around line #1):
1
2
3
4
5
6
<%= form_for(request) do |f| %>
<% if request.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(request.errors.count, "error") %> prohibited this request from being saved:</h2>
<ul>
Products#bigmikepopular113 is the controller view where the original partial is conluded, so essentially the structure is
products/bigmikepopular113.html.erb -> static_pages/_requestquote.html.erb -> requests/_form.html.erb
What can I do differently to make sure I can have an embedded partial?
From what I can see, you're not initializing the creation of a New request anywhere. Only under the new action inside your controller, but there's no view corresponding to that action. You only have the view _form.html.erb.
To clarify: every action in your controller, must correspond to a view, sharing the same name as the action inside the controller. Even if it's a partial.
So, def new automatically points to new.html.erb. def index to index.html.erb and so on.
You therefor have two options. Either create a def form inside the controller, and set up the routes in your routes.rb accordingly, or simply write the statement directly inside the view instead of in the controller:
Remove:
<%= form_for(request) do |f| %>
Instead:
<%= form_for Request.new do |f| %>
Hope that'll help.
So I am confused about how to send back an updated collection of #tasks after the create action so that I can see the newly created item on the page without having to do a refresh. How do I do this? Let me walk you through my code in order.
First, here is my index.html.erb code:
<div class="row">
<div class="col-md-5 col-md-offset-1">
<h2>Tasks</h2>
</div>
<div class="col-md-2 col-md-offset-4">
<%= link_to new_task_path, remote: true do %>
<button class="btn btn-default">New</button>
<% end %>
</div>
</div>
<div class="row">
<div class="col-md-6 col-md-offset-2" id="task-form" style="display:none;"></div>
</div>
<div class="row">
<div class="col-md-7 col-md-offset-1" id="tasks"><%= render #tasks %></div>
</div>
I will click on the "New" button which hits the new action of the controller. Here is my controller code:
class TasksController < ApplicationController
before_action :all_tasks, only: [:create, :update]
before_action :set_tasks, only: [:edit, :update]
respond_to :html, :js
# index action has been removed
def index
#tasks = Task.all
respond_to do |format|
format.html
format.json
end
end
def new
#task = Task.new
end
def create
#task = Task.create(task_params)
end
def update
#task.update_attributes(task_params)
end
private
def all_tasks
#tasks = Task.all
end
def set_tasks
#task = Task.find(params[:id])
end
def task_params
params.require(:task).permit(:description, :deadline)
end
end
This will render the new.js.erb code:
$('#task-form').html("<%= j (render 'form') %>");
$('#task-form').slideDown(350);
This will render the new form:
<%= simple_form_for #task, remote: true do |f| %>
<%= f.input :description %>
<%= f.input :deadline %>
<%= f.button :submit %>
<% end %>
When I hit submit, it will hit the create action of the controller again
def create
#task = Task.create(task_params)
end
After here, what I would like to do is send back an updated collection of #tasks and render them on the page. Is there anyway I can just render the index.html.erb view again and send it Task.all?
Add instance variable #tasks in your def create
def create
#task = Task.create(task_params)
#tasks = Task.all
respond_to do |format|
format.js
end
end
Create a new file create.js.erb
$('#tasks').html("<%= j (render #tasks) %>");
In your case your create.js.erb will be something like this:
$('#tasks').append("<li> <%= #task.inspect %> </li>");
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.
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