Rails Elastics Search Result content URL error - ruby-on-rails

I was just trying out the Elastic Search in my Rails app replacing the existing search function. Everything worked nicely but I am getting http://localhost:3000/contents/video/%23%3CElasticsearch::Model::Response::Result:0x007fe24e118f40%3E url.
in content.rb
def to_param
"#{id}/#{title.parameterize}.html"
#"#{id}-#{title.downcase.slice(0..30).gsub(/[^a-z0-9]+/i, '-')}.html"
end
and in search action
def search
if params[:q].nil?
#indexs = []
else
#indexs = Content.search params[:q]
end
and in views
<% #indexs.each do |f|%>
<%= link_to((truncate f.title, length: 60), {:controller => "contents", :action => "weblinks", :id => f.to_param}, target: "_blank") %>
<% end %>
It works fine for the default listing page, but its URL generating error in search result page. Please help,and also how to replace the {:controller => "contents", :action => "weblinks", :id => f.to_param} with weblinks_path(:format) routes

I assume you use elasticsearch gem, if so you should use records to get ActiveRecord models #indexs.records

Related

undefined method `each' for "#<Complaigns::ActiveRecord_Relation:0x00000003cfb4c8>":String

I have a model, called Complaign, with some other attributes along with the date of complaign (c_date).
In the ComplaignController, I have an index view, which displays all the complaigns. There is a filter which takes from date and to date. On filtering that, it works fine, and properly displays the complaigns fired on those dates.
Now I want the result of this query to be passed on to a different method, say export method.
I thought of passing this from the index view, since it is stored in #complaigns.
This is my index method:
def index
if params[:from] && params[:to]
from = params[:from].to_date
to = params[:to].to_date
#complaigns = Complaigns.where(:c_date => from..to)
else
#complaigns = Complaigns.all
end
end
In the index view, this is what I have written
<%= link_to "Export", {:controller => "complaigns", :action => "export", :complaigns => #complaigns}%>
This is the export method
def export
#complaigns = params[:complaigns]
end
Now, in the export view, when I do the follwing line:
#complaigns.each, I get this error--
undefined method `each' for "#<Complaign::ActiveRecord_Relation:0x00000003cfb4c8>":String
Now this is because, I think, there is no method each in String class. Is there any way, I can convert the String to Complaign type in the method export or while passing it from the index view, pass it as Complaign object instead of String? Is there any other way of doing this?
You can't pass Ruby on Rails model objects directly in the controller parameters, you can pass their corresponding ids and then load the models from the database. HTTP / Ruby on Rails is stateless. If you always go to index before export, one way how to solve this might be:
<%= link_to "Export", {:controller => "complaigns", :action => "export", :complaigns => #complaigns.map(&:id)}%>
def export
#complaigns = Complaigns.find(params[:complaigns])
end
It looks like #complaigs is passed as string instead of actual active_record relations object. You should calculate #camplaigs in export instead of sending them. Or you can pass array of ids
#complaigns.collect(&:id)
HTTP is stateless protocol, which means each request is independent from the other (unless you use cookie or session). For your export method, it knows nothing about the result of index method unless you pass enough information to it. So a simple solution can be:
index view
<%= link_to "Export", {:controller => "complaigns", :action => "export", :from => params[:from], :to => params[:to] }%>
export method
def export
if params[:from] && params[:to]
from = params[:from].to_date
to = params[:to].to_date
#complaigns = Complaigns.where(:c_date => from..to)
else
#complaigns = Complaigns.all
end
end
Here, the parameters for index is passed to export.
But this method is not DRY enough. You can consider using index for export like this:
def index
if params[:from] && params[:to]
from = params[:from].to_date
to = params[:to].to_date
#complaigns = Complaigns.where(:c_date => from..to)
else
#complaigns = Complaigns.all
end
if params[:export].present?
render 'export'
else
render 'index'
end
end
Then in your export link, you can use this:
<%= link_to "Export", {:controller => "complaigns", :action => "index", :from => params[:from], :to => params[:to], :export => true }%>
PS. These codes are not tested. Just for demonstration purpose.
You can't do what you are trying to do. The problem is that when the view is rendered, the resulting HTML is text, and therefore #complaigns is turned into it's equivalent text (the same as #complaigns.to_s).
To do what you want, you need to pass to your link, the same paramaters you used to create #camplaigns in your index view. So:
Change your link to:
<%= link_to "Export", {:controller => "complaigns", :action => "export", :to => params[:to], :from => params[:from]}%>
And then change your export method to:
def export
index
end

Rails routing issue -- trying to post from a form but it is using "GET"

I'm having a problem with submitting a simple form, and I'm not entirely sure what the deal is. The problem, I think, is that I'm trying to submit a form from a User's profile page to another model (ItemShare). Instead of submitting the form via post, it's trying to make a GET request. When I've changed the ItemSharesController to allow for this, it puts ItemShare#index into my modal form, even though I've specified in a billion places that I want it to post. POST!
In my routes.rb:
match '/item_shares' => 'item_shares#create', :via => :post
resources :item_shares, :except => :create
The form:
#share-list-button-dialog.modal.hide.fade{:role => "dialog"}
.modal-dialog
%h3 Share List
.modal-body
=form_for(ItemShare.new, :method => :post, :url => {:action => "create"}) do |f|
=f.hidden_field(:item_id, :value => item.token)
=f.hidden_field(:owner_id, :value =>user.id)
=f.label :shared_user_email, "Your collaborator's email:"
=f.text_field :shared_user_email, :value => "collaborator#example.com"
=f.submit "Share"
ItemSharesController:
class ItemSharesController < ApplicationController
def new
#item_share = ItemShare.new
end
def create
#item_share = ItemShare.new(params[:item_share])
respond_to do |format|
if #item_share.save
format.html {redirect_to user_path(current_user.id), :notice => "List shared successfully"}
else
flash.now[:alert] = "Could not share list."
end
end
end
end
And this is what the stack trace is showing:
Started GET "/item_shares/" for 127.0.0.1 at 2013-10-15 21:40:44 -0400
ActionController::RoutingError (No route matches [GET] "/item_shares"):
actionpack (3.2.11) lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
...
What's going on here??
UPDATE ... finally know what was up.
The form itself was not the problem, but the button I was using to trigger the modal form. I had:
%button{'data-toggle' => 'modal', 'href' => '../item_shares/', 'data-target' => '#share-list-button-dialog'}.
Changed it to this:
=button_to "Share", item_shares_path, "data-toggle" => "modal", "data-target" => "#share-list-button-dialog"
And now it's all working fine. Many thanks to Helios de Guerra for his help and patience. :)
From what you're describing, you should just be using the standard conventions.
Routes:
resources :item_shares
Form:
<%= form_for(ItemShare.new) do |f| %>
...
<% end %>
If it doesn't work, check the source of the rendered page. The form markup should include something like:
<form accept-charset="UTF-8" action="/item_shares" id="new_item_share" method="post">
Upon first glance, I'd say it has something to do with this =form_for(ItemShare.new
In my experience, Rails builds the path from the url in the form_for, which means that yours is going to be messed up with that. You might want to give this a try:
#users/new
def new
#item_share = ItemShare.new
end
#form
=form_for(#item_share
I'm not totally sure on it, but it's my hunch

Missing template error on when background processing

I am using background processing with the resque gem and bioruby, and the processing is correctly functioning. I am however getting a "missing template" error. It seems the action is trying to load a template.
Missing template cosmics/start_batch, application/start_batch with {:locale=>[:en],
:formats=>[:html], :handlers=>[:erb, :builder, :coffee]}.
I do not want a template loaded: the background process retrieves data from an external source and then updates a database table (this is all working).
The code is triggered by a button:
<%= link_to 'Process', start_batch_path, :class =>"btn btn-primary" %>
config/routes.rb
match '/cosmics/start_batch', :to => 'cosmics#start_batch', :as => 'start_batch'
resources :batches do
resources :batch_details
end
cosmics_controller.rb
def start_batch
#batch = Batch.create!(:status => 'created',:status_timestamp => Time.now)
#cosmics = Cosmic.find(:all, :conditions => {:selected => true}).each do |cosmic|
#batch_detail = BatchDetail.create!(:batch_id => #batch.id, :cosmic_mut_id => cosmic.cosmic_mut_id)
#batch_detail.save
cosmic.selected = false
cosmic.save
end
Resque.enqueue(UcscQuery,#batch.id)
end
workers/ucsc_query.rb (Reqsue worker class)
class UcscQuery
require 'bio-ucsc'
include Bio
#queue = :ucsc_queue
def self.perform(batch_id)
Ucsc::Hg19.connect
#batch_detail = BatchDetail.find(:all, :conditions => {:batch_id => batch_id}).each do |batch_detail|
ucsc_cosmic = Ucsc::Hg19::Cosmic.find_by_name(batch_detail.cosmic_mut_id)
if ucsc_cosmic
batch_detail.bin = ucsc_cosmic.bin
batch_detail.chrom = ucsc_cosmic.chrom
batch_detail.chrom_start = ucsc_cosmic.chromStart
batch_detail.chrom_end = ucsc_cosmic.chromEnd
batch_detail.status = 'processed'
batch_detail.save
end
end
Batch.update(batch_id, :status => 'located')
end
end
How can I prevent Rails from trying to load a cosmics/start_batch template? Any refactoring tips would also be appreciated.
If there is no render nor redirect instruction in a controller method, Rails looks for a view with the same name of the method. To change this behavior, add render :nothing => true at the end of the start_batch method.
With this, when the user will click on the Process link, it will render a blank page. That's certainly not what you want. You can use :remote => true option in the link_to so the user will stay on the current page:
<%= link_to 'Process', start_batch_path, {:remote => true}, {id: 'process_btn', :class => "btn btn-primary"} %>
Finally, use javascript to show the user that "something" happened when he clicked on the button. Example:
$('#process_btn').on('click', function() { alert('Batch process started'); };
You can simply type:
render :nothing => true
in your action. I would also advice changing your link to remote
<%= link_to 'Process', start_batch_path, :class =>"btn btn-primary", :remote => true %>
Otherwise you'll see blank page after clicking on it.

How to make a custom route in Rails? By custom I mean one that reacts to params

So essentially I've setup a route to match "products/:product", which seems to respond to a page like baseurl/products/toaster and displays the toaster product. My problem is I can't seem to use link_to to generate this path, and by that I mean I don't know how. Any help on this?
There are several solutions on this one :
<%= link_to 'Toaster', { :controller => 'products', :action => 'whatever', :product => 'toaster' } %>
But it's not really Rails Way, for that you need to add :as => :product at the end of your route. This will create the product_path helper that can be used this way :
<%= link_to 'Toaster', product_path(:product => 'toaster') %>
Within your routes file you can do something like:
match "products/:product" => "products#show", :as => :product
Where the controller is ProductsController and the view is show
within the Products controller your have
def show
#product = Hub.find_by_name(params[:product])
respond_to do |format|
format.html # show.html.erb
end
end
Where whatever is in the products/:product section will be available via params.
Then, since we used :as in your routes you can do this with link_to:
<%= link_to product(#product) %>
Where #product is an instance of a product or a string. This is just an example and the param can be anything you want, the same goes for controller/action. For more info you should check out this.
Hope this helps!

Permalink-fu - Display URL differently

I'm using Ruby on Rails 2.3.8 and permalink-fu plugin. I would like to know how to generate permalinks like this: /posts/44444/this-is-the-title instead of /posts/44444-this-is-the-title
I've tried modifying my Post model as follows:
has_permalink :title, :update => true
def to_param
"#{permalink}"
end
And my routes file as follows:
map.show "/posts/:id/:permalink", :controller => 'posts', :action => 'show'
Then, if I manually type the url with that format, it will work, but if I make a link out of a post in my view as follows, it wont generate the link formatted that way:
<%= link_to p.title, p %>
Where p represents a post.
How can I do so when I call a post like that, I get a permalink formatted as /posts/:id/:permalink instead of /posts/:id-:permalink?
Try this one...
on model:
def to_params
[self.id, self.permalink]
end
on views:
<%= link_to p.title, show_path(p) %>

Resources