Rails Call A Method Lastly In Action - ruby-on-rails

I have something like that in my controller:
def index
#votes = Vote.all
end
private
def search
#votes = OtherVotes.all
end
I want to use search method in index action but I don't want to remove my #votes variable from index. If I use before_action, it calls method before the action so #votes doesn't change. Is it possible to call search method after my votes variable or ignore the variable without removing.

I normally go with this method when I'm looking to build a simple search:
http://railscasts.com/episodes/37-simple-search-form
Create a method in your vote.rb file:
class Vote
def self.search(search)
if search
self.where(:all, conditions: ['name LIKE ?', "%#{search}%"])
else
self.where(:all)
end
end
end
This means when you do Vote.search('term'), you'll bring up any records with a similair name. Replace name for whatever term you're searching for (i.e. title or category).
If there is no search term entered this method simply returns every instance. This means you can leave your controller looking like this:
def index
#votes = Vote.search(params[:search])
end
Finally the view for this would be something like:
<% form_tag votes_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
This will send a get request to the votes_path (the index action on your controller), with the search term parameter. If one is entered the search will return the relevant instances, and if not it will return all.

Try
class TempController < ApplicationController
after_action :search
def index
#votes = Vote.all
end
private
def search
#votes = OtherVotes.all
end
end

Related

Change label's value on form submit - Ruby on Rails

I am brushing up on my rails. I have a dead simple form. views -> genalg -> index.html.erb
<h1>Genalg#index</h1>
<p>Find me in app/views/genalg/index.html.erb</p>
<%= form_with url: "/calculate" do |form| %>
<%= form.text_field :query %>
<%= form.submit "calculate" %>
<% end %>
<% unless #query.nil? %>
<p><%=#query%></p>
<% end %>
I have a controller under controllers -> genalg_controller.rb
class GenalgController < ApplicationController
def index
#query = "biznass"
end
def calculate
puts params
#query = (params[:query].to_i * 2).to_s
render :index
end
end
In routes.rb:
Rails.application.routes.draw do
get 'genalg/index'
post '/calculate', to: 'genalg#index' , as: 'index'
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
How, when I fill the from text :query and hit submit, can I get the text denoted at the very end of my view to display the value I put in times 2 (per the calculate function)? Seems like it should be easy but clearly I have forgotten some basic tenant of how forms and form submission works.
Change the render to redirect_to and pass params like this
def calculate
puts params
#query = (params[:query].to_i * 2).to_s
redirect_to index_path(query: #query)
end
<% unless params[:query].blank? %>
<p><%=#query%></p>
<% end %>
Looking at your routes file, you are calling index action on submitting a post request for calculate so its always returns #query value from the index method i.e. biznass
If you want to calculate #query using params and use index action for that with same routes defined, you have to update index method
def index
if params[:query]
puts params
#query = (params[:query].to_i * 2).to_s
else
#query = 'biznass'
end
OR you can change route and controller code
Rails.application.routes.draw do
get 'genalg/index'
post 'genalg/calculate'
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
class GenalgController < ApplicationController
def index
#query = params[:query] || "biznass"
end
def calculate
puts params
#query = (params[:query].to_i * 2).to_s
redirect_to index_path(query: #query)
end
end
I suggest use resources in your routes.rb instead doing it like that, it will be far more concise, scaleable and you can use url helper method. you can run rake routes in your terminal to see detail of routes, like helper method's name, path, http verb, and which controller's method a path is using.
resources :genalg, controller: :genalg, only: [:index] do
collection do
post :calculate
end
end
in this instance of def calculate, If you have method with http verb POST and it supposed to response with success status, most of the time you need to redirect it instead of rendering it, because in case when user refresh or copy url after calculate, the page will not be found as calculate have POST http verb.
so you have to change render to redirect_to and pass params :query, so every time user refresh the page after calculate, :query will be persisted. even if you want to store :query in database this is still applicable. also, in here you can see we use helper method to redirect to index page by using genalg_index_path
def calculate
puts params
query = (params[:query].to_i * 2).to_s
redirect_to genalg_index_path(query: query)
end
then in index you can check whether params query is empty or not
def index
#query = params[:query] || 'biznass'
end
And in view as you can see we use helper method again to get calculate path, and we don't need #query condition as it never nil
<h1>Genalg#index</h1>
<p>Find me in app/views/genalg/index.html.erb</p>
<%= form_with url: genalg_calculate_path do |form| %>
<%= form.text_field :query %>
<%= form.submit 'calculate' %>
<% end %>
<p><%=#query%></p>

Rails use the same endpoint instead of two new

In my app I need to display purchased Book in one page and planned_purchase Book in other page. The view will be the same so my question is - do I need to create new controller method and routes to display both or can I use e.g. Index and somehow display two different values depending on request?
current code below:
class BooksController < ApplicationController
before_action :fetch_conversation
def index
#planned = Book.planned_purchase
#purchased = Book.purchased
end
end
class Book < ApplicationRecord
scope :purchased, -> { where(purchased: true) }
scope :planned_purchase, -> { where(purchased: false) }
end
As I can understand: you can do this thing using a single controller GET action.
So, you've this BooksController and index action, which I assume can be accessible via books_path.
You can modify the index method, as follows to accept a new parameter by which you can filter the books:
def index
case params[:filter]
when 'purchased'
#records = Book.purchased
when 'planned_purchase'
#records = Book.planned_purchase
else
#records = Book.all
end
end
Now, you have a view page books/index.html.erb for this index action. Let's break this into 2 separate partials.
In books/index.html.erb:
<% if params[:filter] == 'purchased' %>
<%= render "partial_for_parchased" %>
<% elsif params[:filter] == 'planned_purchase' %>
<%= render "partial_for_planned_parchased" %>
<% end %>
Inside those partials you can modify the view based on the category.
Now, to get those two different page, you need to define 2 separate urls:
<%= link_to 'Purchased', books_path(filter: 'purchased') %>
<%= link_to 'Planned Purchased', books_path(filter: 'planned_purchase') %>
As your, def index, is a GET method and not depending on the strong parameters, so you don't need to add filter in your params.required(:book).permit(...)
Hope I covered all the areas!
I think the answer should be pretty simple and straight.
You can just pass a parameter to the index method and filter records inside it and return them.
def index
case params[:filter]
when 'purchased'
#records = Book.purchased
when 'planned_purchase'
#records = Book.planned_purchase
else
# get all records or throw an error
end

Sending search term from view to service via controller in rails

I am having a hard time understanding search in rails. I want to send search term from my view to service. I have this code in my service:
class Searching
def search_term
drive_auth.list_files(q: "fullText contains 'term'",
spaces: 'drive',
fields: 'nextPageToken, items(id, title)')
end
end
And this code in controller:
class SearchController < ApplicationController
def index; end
def show
//here I should take term from search box and send to
search_term in service instead of word 'term'
end
end
And this is my view (I understand it's not full code, that's why I need help)
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
What I want is to search from index.html.erb and show results in show.html.erb page on click. How to send this parametar to search method in service and show results in html?
If you want to send params[:search] to from your controller to service, below code may solve your issue:
In controller:
class SearchController < ApplicationController
def index; end
def show
result = Searching.new.search_term(params[:search])
# Your code to use result
end
end
In service:
class Searching
def search_term(q)
drive_auth.list_files(q: "fullText contains '#{q}'",
spaces: 'drive',
fields: 'nextPageToken, items(id, title)')
end
end

Simple search on a Globalize3 table in Rails

I am looking to implement a simple search function while using the globalize3 gem for Ruby on Rails. Since the translations of the model are stored in a separate table, the code below doesn't work as there is no longer a :name field in the products table. How can I adjust the code below to make the search function correctly?
products_controller.rb
#products = Product.search(params[:search]).all
index.html.erb
<%= form_tag products_path, method: :get do %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", name: nil %>
<% end %>
model
class Product < ActiveRecord::Base
translates :name
attr_accessible :name, :price, :released_at
def self.search(search)
if search
where('name LIKE ?', "%#{search}%")
else
scoped
end
end
end
You're in luck, I tackled exactly the same problem recently!
Luckly for you the answer is quite simple. You can use the class method with_translations to include translations for a given set of locales.
Here's the code:
def with_translations(*locales)
locales = translated_locales if locales.empty?
includes(:translations).with_locales(locales).with_required_attributes
end
Include it in your search method:
def self.search(search)
if search
with_translations.where('name LIKE ?', "%#{search}%")
else
with_translations
end
end
That should do it.
As an added note: you could add an optional locales parameter to the search method and pass it to with_translations to optionally narrow the search to terms in a particular language, say for example in the current locale.
Solved ...
def index
if params[:search]
#at = []
#at = Array.new
Article.translation_class.where("title LIKE ? OR description LIKE ?","%#{params[:search]}%","%#{params[:search]}%").all.each do |t|
#at.push t.article_id
end
#articles = Article.where(id: #at).recent_first.paginate(page: params[:page], per_page: 5)
else
#articles = Article.all.recent_first.paginate(page: params[:page], per_page: 5)
end
end

How to implement simple search form to be used in conjunction with paginate?

I am following Ryan Bates' railcasts: http://railscasts.com/episodes/37-simple-search-form
in solving my issue with the search results on a page with will-paginate.
Here he answers the question as to how to solve this problem. However, I've tried them and haven't had any luck. From following his second resolution, I get a NoMethod error for "search_conditions" as the result.
The Code:
projects/index.rhtml
<% form_tag projects_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
projects_controller.rb
def index
#projects = Project.search(params[:search])
end
models/project.rb
def self.search(search)
if search
find(:all, :conditions => ['name LIKE ?', "%#{search}%"])
else
find(:all)
end
end
His Answers:
One way is to call the class method "search_conditions" and instead of having it do the find it will just return a conditions array so you could use it in the paginate method.
Course.paginate(:all, :conditions => Course.search_conditions(..))
Another is to call the method "paginated_search" and have it call "paginate" instead of "find".
Lastly you could have the search method accept a block which uses with_scope to set the find conditions. This way you could call "paginate" in that block and the conditions will automatically be applied.
Can someone explain to me how I should go about solving this? I am new to rails and maybe I am just misunderstanding what he is saying.
Railscast you following is pretty old, lots changed since then. Try to change implementation of search method like this:
def self.search(search)
if search
where 'name LIKE ?', "%#{search}%"
else
scoped
end
end
and something like this in controller:
def index
#projects = Project.search(params[:search]).paginate(:page => params[:page])
end

Resources