Paginate Result from rails console - ruby-on-rails-4

I'm trying to paginate the result from thinking sphinx in rails console without any pagination gem. Is it possible to do?

Yes, it is possible. Thinking Sphinx does not require any pagination gems… you can either use the :per_page and :page options in a search request:
# page: the page of results, defaults to 1 (the first page).
# per_page: number of results in each set, defaults to 20.
Article.search "pancakes", :page => 2, :per_page => 50
These are the same options as WillPaginate - and the resulting search results object can be used with the WillPaginate view helper - but you do not need WillPaginate to use these options.
There is also the possibility to use the per_page method on a search results object, like with Kaminari - but again, Kaminari is not required (even though the search results object can also be used with Kaminari's view helper):
articles = Article.search("pancakes")
articles.per_page(10)
There is also the :offset option, if you wish to calculate the number of results to skip (rather than using :page and :per_page to automate such calculations).

Related

How does ransack search works on an array list?

I am using Rails 4.2.5, Ruby 2.2, ransack.
I am trying to implement search functionality using Ransack. I have something like:
emails = ["abc#abc.com", "a#a.com", "b#b.com"]
users_list = emails.map{|a| User.where(email: a).first}
checked_in_users = Kaminari.paginate_array(users_list)
This gives me proper list of users in the page. But if I want to search by email, what should I do ?
#q = checked_in_users.ransack params[:q]
This gives me:
"NoMethodError (undefined method `ransack' for #<Array"
HAML code:
= search_form_for [#q], url: users_path(some_id: id) do |form|
= form.text_field :user_name_or_user_email_cont, placeholder: 'Name or email', class: 'form-control'
What would be the correct way to do it with ransack ?
If you want to search the entire list of users, you could do something like this:
#q = User.ransack(params[:q])
#users = #q.result.page(params[:page])
You want to call ransack on your model prior to adding pagination. Once you have the ransack result, you can add pagination. This section of the documentation shows you how to handle pagination with ransack. In its most basic form, this is how you can use ransack.
Also, it looks like you have some odd code in your example. Apologies if I'm misunderstanding what you're trying to do.
When you call emails.map{|a| User.where(email: a).first}, you're making a where query 3 times in this case and returning an array of 3 models. Ransack won't operate on that array.
I would change it to something like this in your case:
emails = ["abc#abc.com", "a#a.com", "b#b.com"]
#q = User.where(email: emails).ransack(params[:q])
#checked_in_users = #q.result.page(params[:page])
Just know that you'd be searching from an array of users with emails of "abc#abc.com", "a#a.com", and "b#b.com". If you search with your ransack form for "bob#example.com", you wouldn't get any search results. This may not be what you want.

Rails 4.2 - How to properly use rails sanitize to protect against cross scripting vulnerabilites

I am on rails 4.2.1 (ruby 2.2.1p85) and I want to sanitize user input and also have that text cleared out of the post/get params. I don't want to solely depend on native rails 4 auto escaping.
Being a bit new to rails I was not aware of the sanitize options.
http://api.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html
I was originally going to create a helper for such purposes so I could do something as shown below. I'm trying to sanitize form input to secure against Cross-site scripting (XSS) vulnerabilities.
basic helper example This works but its probably not the best rails way to do it? Also the text is still in the post/get request.
<%= text_field_tag :input_text, Safetxt(params[:input_text]) %>
helper method
def Safetxt(input_value)
txtOut = input_value
if txtOut.blank?
txtOut = ""
else
txtOut = txtOut.gsub("<script>", "")
txtOut = txtOut.gsub("</script>", "")
end
return txtOut
end
on submit the input_text is cleaned on output but the get/post values still contain the stripped values.
input_text=<script>alert%28"blah"%29<%2Fscript>
How can I utilize a custom scrubber in a helper method to properly sanitize input (remove dangerous text,tags)? I'm a bit confused how to implement this properly with custom rules.
For example something as shown below (I know this is wrong). Also what is the best way to exclude that text in the post/get request as well? I know I should sanitize the text in the controller side for input, but if there is a way, I'd like that text to be cleared on the submit request if that's possible.
def Safetxt(input_value)
scrubber = Rails::Html::TargetScrubber.new
scrubber.tags = ['script']
txtOut = input_value
if txtOut.blank?
txtOut = ""
else
txtOut.scrub!(scrubber)
end
return txtOut
end
You can use the Rails 4 sanitize method to strip out tags that are not "whitelisted" by default by rails.
So in your controller code you can have:
ActionView::Base.new.sanitize("<script>alert('hello')</script>")
which would strip out the script tag. You can whitelist your own attributes or elements rather than the default or if you want more custom behavior you can define your own scrubber in the sanitize method.

Rails 4 not passing permitted parameters

Apologies for posting what seems to be an oft-asked question but I have toiled for two days without getting closer.
I am running Rails 4.0.1 (with Devise, CanCan, among others) and have user and role models with a HABTM users_roles table (as created by the since-removed rolify).
class Role < ActiveRecord::Base
has_and_belongs_to_many :users, :join_table => :users_roles
belongs_to :resource, :polymorphic => true
attr_reader :user_tokens
def user_tokens=(ids)
self.user_ids = ids.split(",")
end
end
My submitted form data is:
"role"=>{"name"=>"disabled", "resource_id"=>"", "resource_type"=>"Phone", "user_tokens"=>["", "3"]}
(Not sure where the empty string comes from; it's not in the option list, but hey, welcome to Rails).
My problem is with getting the user_tokens data passed into the appropriate variable in the controller.
There are lots of postings suggesting the correct format (e.g., how to permit an array with strong parameters)
If I specify the permitted parameters thus:
params.require(:role).permit(:name, :resource_id, :resource_type, :user_tokens => [] )
I get a '500 Internal server error' with no other details.
If I specify the permit as
params.require(:role).permit(:name, :resource_id, :resource_type, user_tokens: [] )
I don't get any errors (No unpermitted parameters in the dev log) but the user_tokens array is not passed through in the #role.
If I run this scenario through a console I get:
params = ActionController::Parameters.new(:role => {:resource_id => "", :resource_type => "Phone", :user_tokens => ["", "3"]})
params.require(:role).permit(:name, :resource_id, :resource_type, user_tokens: [] )
=> {"resource_id"=>"", "resource_type"=>"Phone", "user_tokens"=>["", "3"]}
params.require(:role).permit(:user_tokens).permitted?
Unpermitted parameters: resource_id, resource_type, user_tokens
=> true
I'm stuck as to where I should try looking next.
Even though I was sure I had already tried it, changing the model to be
def user_tokens=(ids)
self.user_ids = ids
end
fixed it. I've always struggled to understand this bit of notation except when I've spent 4 days trying why my many:many models don't work.
I guess it'd be easier if I was doing this full time rather than just for particular sysadmin projects.

RailsAdmin papertrail empty history

I have configured RailsAdmin to use papertrail for showing the history of changes on models.
It seems to be working fine, but in the UI it displays changes always as an empty array. Is this the expected output? I was expecting to see the actual changes made on the records, or even better a drill down with a before and after change on the record.
Rails 4, RailsAdmin 0.5, PaperTrail 2.7.2
You need to have a column called object_changesin your versions table.
See these instructions from paper_trail. Look at the section called "Diffing Versions."
In short, when you generate the versions table, do this rails g paper_trail:install --with-changes
Or, if you already have an objects table, do this migration:
class AddObjectChangesColumnToVersions < ActiveRecord::Migration
def self.up
add_column :versions, :object_changes, :text
end
def self.down
remove_column :versions, :object_changes
end
end
I'm seeing the exact same thing and filed a bug report with rails_admin: https://github.com/sferik/rails_admin/issues/1751
If that is addressed I'll update this comment.

Redmine - Add "Spent Time" Field to Issues Display

How would I go about adding the "Spent Time" as a column to be displayed in the issues list?
Consolidating Eric and Joel's answers, this is what I needed to do to get a 'Spent time' column added to Redmine 1.0.3. Not sure if there's a better way to get the translation text added.
To give the new field a localised name, added to config/locales/en.yml around line 299 at the end of the field definitions:
field_spent_hours: Spent time
To add the new column, created lib/spent_time_query_patch.rb with content:
# Based on http://github.com/edavis10/question_plugin/blob/master/lib/question_query_patch.rb
require_dependency 'query'
module QueryPatch
def self.included(base) # :nodoc:
base.extend(ClassMethods)
# Same as typing in the class
base.class_eval do
unloadable # Send unloadable so it will not be unloaded in development
base.add_available_column(QueryColumn.new(:spent_hours))
end
end
module ClassMethods
unless Query.respond_to?(:available_columns=)
# Setter for +available_columns+ that isn't provided by the core.
def available_columns=(v)
self.available_columns = (v)
end
end
unless Query.respond_to?(:add_available_column)
# Method to add a column to the +available_columns+ that isn't provided by the core.
def add_available_column(column)
self.available_columns << (column)
end
end
end
end
To get the spent_time_query_patch above to actually load, created config/initializers/spent_time_query_patch.rb with content:
require 'spent_time_query_patch'
Query.class_eval do
include QueryPatch
end
You can also do this by adding the column at runtime. This will add the spent hours column without modifying the Redmine core. Just drop the following code into a file in lib/
Adapted from:
Redmine Budget Plugin
Redmine Question Plugin
require_dependency 'query'
module QueryPatch
def self.included(base) # :nodoc:
base.extend(ClassMethods)
# Same as typing in the class
base.class_eval do
unloadable # Send unloadable so it will not be unloaded in development
base.add_available_column(QueryColumn.new(:spent_hours))
end
end
module ClassMethods
unless Query.respond_to?(:available_columns=)
# Setter for +available_columns+ that isn't provided by the core.
def available_columns=(v)
self.available_columns = (v)
end
end
unless Query.respond_to?(:add_available_column)
# Method to add a column to the +available_columns+ that isn't provided by the core.
def add_available_column(column)
self.available_columns
Also, it would be cool, if the column "Spent time" was sortable.
After looking up the produced SQL, I just implemented the sortable feature this in this way:
base.add_available_column(QueryColumn.new(:spent_hours,
:sortable => "(select sum(hours) from time_entries where time_entries.issue_id = t0_r0)")
)
Replace the respective line. I just hope the issue_id column's name is always "t0_r0" ...
PS: You can find lots of examples in app/models/query.rb lines 122++
2-Digits Problem:
Unfortunatly, I had to hack one of the core files: app/helpers/queries_helper.rb
Around line 44, change this:
when 'Fixnum', 'Float'
if column.name == :done_ratio
progress_bar(value, :width => '80px')
else
value.to_s
end
into:
when 'Fixnum', 'Float'
if column.name == :done_ratio
progress_bar(value, :width => '80px')
elsif column.name == :spent_hours
sprintf "%.2f", value
else
value.to_s
end
EDIT: Using a patch instead manipulating the source Recently, we did an update of the redmine system, so the above mentioned Fix also was removed.
This time, we decided to implement that as a patch.
Open up any plugin (We created a plugin for our monkey-patch changes on core). open up vendor/plugins/redmine_YOURPLUGIN/app/helpers/queries_helper.rb
module QueriesHelper
def new_column_content(column, issue)
value = column.value(issue)
if value.class.name == "Float" and column.name == :spent_hours
sprintf "%.2f", value
else
__column_content(column, issue)
end
end
alias_method :__column_content, :column_content
alias_method :column_content, :new_column_content
end
This feature build in from 1.4.0 version
by using AgileDwarf plugin. You can have spent time & you can say for what you spent this time (developement - design -...)
Since no one answered, I just poked the source until it yielded results. Then I started a blog to explain how I did it.
Add spent time column to default issues list in Redmine