I wondering what would be the best practice to perform next task.
I have a search results to display from index action. Every individual record displays in the pop up through show action.
What I would love to do is to execute pop up if there is only one record found.
Here what I already tried.
def index
#companies = Company.search(params[:query]).results
#count = #companies.total
if #count == 1
return
render company_path
end
end
Seems like return, redirect_to or render aren't play well in one action.
Any other thought of doing it?
UPDATE added show action
def show
sleep 1/2
client = Elasticsearch::Client.new host:'127.0.0.1:9200', log: true
response = client.search index: 'companies', body: {query: { match: {_id: params[:id]} } }
#company = response['hits']['hits'][0]['_source']
respond_to do |format|
format.html # show.html.erb
format.js # show.js.erb
format.json { render json: #company }
end
# more code
end
The return is definitely killing you, but you're trying to render / redirect to a path for a specific resource without specifying the resource. I've taken a stab at something that might work a bit better for you:
class MyController
before_action :find_companies, only: :index
before_action :find_company, only: :show
before_action :show_company_if_matched, only: :index
def index
# do whatever you were doing here...
end
def show
respond_to do |format|
format.html # show.html.erb
format.js # show.js.erb
format.json { render json: #company }
end
# more code
end
private
def find_companies
#companies = Company.search(params[:query]).results
end
def find_company
client = Elasticsearch::Client.new host:'127.0.0.1:9200', log: true
response = client.search index: 'companies', body: {query: { match: {_id: params[:id]} } }
#company = response['hits']['hits'][0]['_source']
end
def show_company_if_matched
redirect_to company_path(#comapnies.first) if #companies.total == 1
end
end
EDIT: Updated to include show action
This is correct syntax :
def index
#companies = Company.search(params[:query]).results
#count = #companies.total
if #count == 1
render company_path # no params ?
return
else
redirect_to root_path
return
end
end
Use return after render or redirect it's good practice, because in some cases 'render' or 'redirect_to' do not do 'return' (cf: best practice ruby)
Remove the return from your controller. If I've understood your question, this should result in the behavior you're looking for:
if #count == 1
render company_path
else
# Do something else
end
If there is subsequent code in the controller that you do not want to execute, you can render and return as follows:
if #count == 1
render company_path and return
else
# Do something else
end
Related
I had the following code in my create action.
tasks_comtroller.rb
def create
#task = current_user.tasks.build(task_params)
#task.complete = false
n=1
loop do
unless Task.find_by priority: n
#task.priority=n
break
end
n+=1
end
respond_to do |format|
if #task.save
format.html { redirect_to user_tasks_path(current_user) }
format.js
else
format.html { render action: 'new' }
format.js
end
end
end
Then I took out some part I made a method inside my task model.
class Task < ActiveRecord::Base
def priority_increment
n=1
loop do
unless Task.find_by priority: n
#task.priority=n
break
end
n+=1
end
end
end
How can I now correctly invoke this method from controller?
Thats really inefficient since each iteration has to do a database query - instead do Task.order(:priority).first and let the database do the work.
class Task < ActiveRecord::Base
def self.heighest_priority
# .try lets us handle the case where there
# are no Tasks gracefully
p = Task.order(:priority).first.try(:priority)
# return the highest + 1 or 1 if there are no tasks.
p ? p + 1 : 1
end
end
Calling methods in ruby in exactly the same no matter where you are calling the function:
obj.some_method # in Ruby the parens are optional
obj.some_method(someArg)
obj.some_method(someArg) do
# blocks are awesome.
end
Here we have a class method - we call it by Task.heighest_priority.
So lets refactor the create method to use our new method:
def create
#task = current_user.tasks.build(task_params) do |t|
t.priority = Task.heighest_priority
t.complete = false
end
if #task.save
format.html { redirect_to user_tasks_path(current_user) }
format.js
else
format.html { render action: 'new' }
format.js
end
end
If you want to put that part of code into the model, you have to call self instead of the instance variable #task like so:
class Task < ActiveRecord::Base
def priority_increment
n=1
loop do
unless Task.find_by priority: n
self.priority=n
break
end
n+=1
end
end
end
Afterwards you can call it on the task instance:
#task.priority_increment
My controller action perform_review is responding with json. As long as there are an order to fetch, a view partial is re-rendered by perform_review.js.erb with the new order, but when we are out of orders to review, perform_review.js.erb should redirect to an other page.
The controller looks like this:
## orders_controller.rb
class OrdersController < ApplicationController
def perform_review
...
#order = get_order
respond_to do |format|
format.html {
redirect_to orders_path(current_user)
}
format.js {
if #order == nil
#redirect_path = orders_path
return
end
}
end
end
end
And here is the js.erb file:
## perform_review.js.erb
if ("<%=#redirect_path %>" != "") {
location.href = "<%=#redirect_path %>";
}
else
var order_options_partial = $("#order_options_partial");
order_options_partial.children().remove();
order_options_partial.append('<%= j render("order_options") %>');
The else part works just fine, but the if part does not. The curious thing is that everything is OK in the controller, and #redirect_path gets assigned with "/orders". However, it looks like perform_review.js.erb does not get triggered after this. To be sure of this I have tried to put in a line that said console.log("Starting perform_review.js.erb");, but it does not get called in the browser console...
You can do it in controller as well
class OrdersController < ApplicationController
def perform_review
...
#order = get_order
respond_to do |format|
format.html {
redirect_to orders_path(current_user)
}
format.js {render :js => "window.location.href = '"+orders_path(current_user)+"'"} if #order.blank?
end
end
end
In this way you do not need the if else in your perform_review.js.erb.
And if you want to do in the view file, then here is the following code.
<% if (#order.blank?) %>
window.location.href = "<%= escape_javascript(#redirect_path) %>";
<% else %>
// your code
<% end %>
I want to override Kaminari's pagination when rendering JSON, or tell it to return all with pagination.
In App1, I am using ActiveResource to access App2's Group model:
class Group < ActiveResource::Base
self.site = "http://www.app2.com:3000"
end
Here's App2's Group model:
class Group < ActiveRecord::Base
default_scope order('name asc')
paginates_per 10
This is my controller. The Group.search stuff is ransack:
class GroupsController < ApplicationController
# GET /groups
# GET /groups.json
def index
#search = Group.search(params[:q])
#groups = #search.result.page params[:page]
respond_to do |format|
format.html # index.html.erb
format.json { render json: #groups }
end
end
I've added eleven groups to App2. In the console of App1 I get:
[45] pry(main)> Group.all.count
=> 10
What is the best way to do this without changing the HTML pagination rendering?
You can prepare all the common logic you need but only apply pagination for the HTML format:
def index
#search = Group.search(params[:q])
#groups = #search.result
respond_to do |format|
format.html { #groups = #groups.page(params[:page]) }
format.json { render :json => #groups }
end
end
You can run different code in different formats:
def index
respond_to do |format|
format.html {
#search = Group.search(params[:q])
#groups = #search.result.page params[:page]
} # index.html.erb
format.json {
render json: Group.all
}
end
end
This is my controller. def random_generate is not giving me any output, and when I create the object, length is there but random_primer_generated is empty. Can someone help me?
class GeneratorsController < ApplicationController
before_action :set_generator, only: [:show, :edit, :update, :destroy]
helper_method :random_generate
# GET /generators
# GET /generators.json
def index
#generators = Generator.all
end
# GET /generators/1
# GET /generators/1.json
def show
end
# GET /generators/new
def new
#generator = Generator.new
end
# GET /generators/1/edit
def edit
end
# POST /generators
# POST /generators.json
def create
#generator = Generator.new(generator_params)
respond_to do |format|
if #generator.save
format.html { redirect_to #generator, notice: 'Generator was successfully created.' }
format.json { render action: 'show', status: :created, location: #generator }
else
format.html { render action: 'new' }
format.json { render json: #generator.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /generators/1
# PATCH/PUT /generators/1.json
def update
respond_to do |format|
if #generator.update(generator_params)
format.html { redirect_to #generator, notice: 'Generator was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #generator.errors, status: :unprocessable_entity }
end
end
end
# DELETE /generators/1
# DELETE /generators/1.json
def destroy
#generator.destroy
respond_to do |format|
format.html { redirect_to generators_url }
format.json { head :no_content }
end
end
def random_generate
if #generator.choice == 'Randomly'
length = #generator.primer_length
chars = 'atgc'
seq = ''
#length = length.to_i
length.times { seq << chars[rand(chars.size)] }
#generator.random_primer_generated = seq
end
return #generator.random_primer_generated
end
private
# Use callbacks to share common setup or constraints between actions.
def set_generator
#generator = Generator.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def generator_params
params.require(:generator).permit(:primer_length, :choice_random_primer_generated)
end
end
This is my Form_VIEW (to get the user's data - length and choice):
<%= form_for (#generator ) do |f| %>
<% if #generator.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#generator.errors.count, "error") %> prohibited this generator from being saved:</h2>
<ul>
<% #generator.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<label>Primer Length</label><br>
<%= f.number_field :primer_length %>
</div>
<label>Selection :</label><br>
<label>Randomly</label>
<%= radio_button_tag(:choice_random_primer_generated, 'Randomly')%>
<%= button_to('Generate', random_generate_generator_path(#generator))%>
<% end %>
Note: the form may be a red herring here. If you only want the code to be randomly generated when the user explicitly clicks that button, and NOT after every create or save, then you don't want any callbacks. You're doing it the right way. The only thing you are missing is the save call at the end of your method, and you'll also want to redirect the user back to a page.
However, if you DO want generate to happen after EVERY create or update, then you should probably change that button_to call to f.submit, and move that random_generate code to your model. Then, you can use rails callback for after_save and call that method from there within your controller.
More info:
http://guides.rubyonrails.org/active_record_callbacks.html
You are not calling your helper_method anywhere. When you post the form and it reaches the server, the create method is called. The helper_method is not triggered, therefore you are not creating a random number.
I didn't understand it very well, but what are you trying to randomize? Why don't you simply use a rand(999) to randomize numbers for example?
It looks like you want to call random_generate after your new and create action, but you are not calling it. All you have to do is change helper_method :random_generate to after_action :random_generate, only: [:create, :new]
You also want to make sure to save your new record in random_generate. You don't need the return #genator.random_primer_generated. See below:
def random_generate
if #generator.choice == 'Randomly'
length = #generator.primer_length
chars = 'atgc'
seq = ''
#length = length.to_i
length.times { seq << chars[rand(chars.size)] }
#generator.random_primer_generated = seq
end
#generator.save!
end
Here i send the user.id as params dd
<h3><%= link_to("Lend Asset", {:controller => 'empassets', :action=> 'index', :dd => user.id})%></h3>
In controller empassets i fetch it by
def index
#id = params[:dd]
#empassets = Empasset.where(:ad => #id)
respond_to do |format|
format.html # index.html.erb
format.json { render json: #empassets }
end
end
def show
#id = params[:dd]
#empasset = Empasset.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #empasset }
end
end
def new
#id = params[:dd]
#empasset = Empasset.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #empasset }
end
end
def edit
#id = params[:dd]
#empasset = Empasset.find(params[:id])
end
I need this #id in all new show edit method. But it takes in index only as i mention it in index. How can i make such that if Lend asset is click then #id= params[:id] have value in all methods. How can it is possible to make it available for another #id = params[:id] is not send in that controller?
Maybe will be better if you store the current user in session and after that, capture the user model with a filter in the controller, like this:
# controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_filter :set_current_user_in_model
private
def current_user
#current_user ||= User.find(params[:dd]) || User.new
end
# This method save the current user in the user model, this is useful to have access to the current user from a model and not from the controller only
def set_current_user_in_model
User.current_user current_user if not current_user.nil?
end
end
# models/user.rb
class User < ActiveRecord::Base
#...
# This is useful to get the current user inside a model
def self.current_user(user = nil)
##current_user = (user || ##current_user)
end
#...
end
Basically, my idea is store that information inside a model with a filter, you can use session if you wanth to get the information (user id).
def index
session[:user_id] = params[:dd]
#empassets = Empasset.where(:ad => session[:user_id])
respond_to do |format|
format.html # index.html.erb
format.json { render json: #empassets }
end
end
def show
#empasset = Empasset.find(session[:user_id] || params[:dd])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #empasset }
end
end
Note I used session[:user_id] || params[:dd] because maybe, the session information was not stablished and you give it :dd parameter. But if you want to stablish the #id variable, you can use a filter like before.
But I don't know what is the main problem.
Edit
# controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_filter :set_dd_param, :except => :index
def index
session[:dd] = params[:dd] # Here you write the session
#current_user ||= User.find(params[:dd]) || User.new
end
# ...
protected
def set_dd_param
params[:dd] = session[:dd] || -1 # Here you read the session a write the params variable
end
end
Sorry for the delay.
Unless you want to store it to the session, there is no way to automatically make #id available to every method in the controller.. but you can add the param to each link/form, like so:
<%= link_to("New Asset", {:controller => 'empassets', :action=> 'new', :dd => #id})%>
<%= link_to("Show Asset", {:controller => 'empassets', :action=> 'show', :dd => #id})%>
where these links are in the index view and #id is set in the index method.
Not exactly sure what the goal is here, but something like this may work.
def index
$id = params[:dd]
#empassets = Empasset.where(:ad => #id)
respond_to do |format|
format.html # index.html.erb
format.json { render json: #empassets }
end