Activerecord array to a variable. - ruby-on-rails

I need to get the contents of an activerecord array into a variable.
<%= select_tag :operators,
options_for_select(#operator_list,
:selected => previous_operators(params[:id], action_name)),
),
{:multiple => true, :size => 11}
%>
previous_operators gets the contents of the operators column (an array)
def previous_operators(id, action)
if action_name != "new" && action_name != "create" # prevent error if a new bedsheet line.
#slitter_bedsheet = SlitterBedsheet.find(id) # grab the current bedsheet line
#previous_operators = Array.new
#previous_operators = #slitter_bedsheet.operators # get the keywords for the current bedsheet line
end
if #previous_operators.present?
operators = Array.new
operators = eval(#previous_operators)
else
# operators = ''
end
return operators
end
The content of operators will look something like
["", "[\"Chris Mendla\"]"]
To summarize, I am trying to get the contents of #slitter_bedsheet.operators into the selected line :selected => previous_operators(params[:id], action_name)).
So far, the selected option is not working in that no items are shown as already selected.

I solved this by using the eval function. I realize that this is a dangerous function but in this case it is an app that is inside our firewall and the input is coming from a select box. There might be another way of doing this but this will work for now.
:selected => eval(previous_operators(params[:id], action_name))

Related

Get key names from key value pairs

I'm running Rails 4 on Ruby 2.0
I'm trying to populate a select tag with a key value pair array I have setup in my model. However, I am having trouble figuring out how to grab the key. Here is what I have so far:
Model
class Store
Colors = ['blue', 'green', 'red', 'yellow', 'orange', 'pink', 'purple', 'lime', 'magenta', 'teal']
SearchParams = {'isbn' => 'ISBN', 'intitle' => 'Title', 'inauthor' => 'Author', 'inpublisher' => 'Publisher', 'subject' => 'Subject', 'lccn' => 'LCCN', 'oclc' => 'OCLC'}
end
Controller
def index
#search_params = Store::SearchParams.map { |param| [param, param.key] }
end
note: I am aware that .key does not exist - I added that hoping it would better communicate what I am trying to do.
View
<%= form_tag do %>
<%= select_tag :param_name, #search_params, prompt: 'choose' %>
<% end %>
I would like the value of each <option> to be the key, and for the user to see the value. I hope that makes sense.
You generally use options_for_select to provide the options for select_tag. Conveniently, you can hand a Hash to options_for_select and it will do the right thing:
options_for_select(container, selected = nil)
Accepts a container (hash, array, enumerable, your type) and returns a string of option tags. [...]
The problem is that options_for_select wants the Hash's keys to be what the human sees and the values to be the value attributes for the <option>s. Your Hash is backwards but you can use Hash#invert to flip the keys and values around:
invert → new_hash
Returns a new hash created by using hsh’s values as keys, and the keys as values.
So you could just do this in your controller:
#search_params = Store::SearchParams.invert
and then this in the ERB:
<%= select_tag :param_name, options_for_select(#search_params), prompt: 'choose' %>
I think, this itself will work
def index
#search_params = Store::SearchParams.to_a
//it will return the array you want, but the values will be [[key1,value1],[key2,value2]]
// if you want to reverse itm then Store::SearchParams.to_a.collect{|arr| arr.reverse} will give that
end
That will do it:
def index
#search_params = Store::SearchParams.map { |key, val| [val, key] }
end
UPD: consider also Hash#invert (thanks to #mu is too short)

Rails issue with params hash

I need to export a previously rendered table from my view to pdf. When I build the array of hashes as follows:
__index = 0
#people.each do |p| %>
#pdfdata[__index] = {
[:name] => p.name.to_s,
[:surname] => p.surname.to_s
__index += 1
end
end
and send it to the controller in order to export it on a pdf as follows:
hidden_field_tag(:pdfdata, #pdfdata)
when I get the params[:pdfdata] I cannot find a way unless I build a string parser to map the data accordingly... is there a better way to do this?
Modifying your code a little bit to get
#people.each_with_index do |p,i| %>
#pdfdata[i] = {
[:name] => p.name.to_s,
[:surname] => p.surname.to_s}
end
and use this gem to create the hidden has field
https://github.com/brianhempel/hash_to_hidden_fields

ActiveAdmin - Can a resource contain a custom block, AND be sortable?

I'm trying to basically have a toggle switch for a resource.... However when i pass the block as the second option, i can no longer sort by that column.
column :Playable do |level|
link_to level.playable || 'false', "levels/#{level.id}/toggle"
end
# ... later
member_action :toggle do
level = Level.find(params[:id]);
level.update_attribute("playable", !level.playable)
redirect_to(:back)
end
Please try:
column :Playable, :sortable => :playable do |level|
...
end

Optional parameters for Rails Image Helper

In my current Rails (Rails 2.3.5, Ruby 1.8.7) app, if I would like to be able to define a helper like:
def product_image_tag(product, size=nil)
html = ''
pi = product.product_images.first.filename
pi = "products/#{pi}"
pa = product.product_images.first.alt_text
if pi.nil? || pi.empty?
html = image_tag("http://placehold.it/200x200", :size => "200x200")
else
html = image_tag(pi, size)
end
html
end
...and then call it from a view with either:
<%= product_image_tag(p) %>
...or:
<%= product_image_tag(p, :size => 20x20) %>
In other words, I'd like to be able to have this helper method take an optional size parameter. What would be the best way to go about this?
You're on the right track. I would do this:
def product_image_tag(product, options = {})
options[:size] ||= "200x200"
if img = product.product_images.first
image_tag("products/#{img.filename}", :alt => img.alt_text, :size => options[:size])
else
image_tag("http://placehold.it/#{options[:size]}", :size => options[:size])
end
end
Explanations:
Setting the final parameter to an empty hash is a common Ruby idiom, since you can call a method like product_image_tag(product, :a => '1', :b => '2', :c => '3', ...) without explicitly making the remaining arguments a hash with {}.
options[:size] ||= "200x200" sets the :size parameter to 200x200 if one wasn't passed to the method.
if img = product.product_images.first - Ruby lets you do assignment inside a condition, which is awesome. In this case, if product.product_images.first returns nil (no image), you fall back to your placehold.it link, otherwise display the first image.

Passing hash as values in hidden_field_tag

I am trying to pass some filters in my params through a form like so:
hidden_field_tag "filters", params[:filters]
For some reason the params get changed in the next page. For example, if params[:filters] used to be...
"filters"=>{"name_like_any"=>["apple"]} [1]
...it gets changed to...
"filters"=>"{\"name_like_any\"=>[\"apple\"]}" [2]
note the extra quotations and backslashes in [2] when compared to [1].
Any ideas? I'm attempting to use this with searchlogic for some filtering, but I need it to persist when I change change objects in forms. I would prefer not to have to store it in session.
My solution was just to re-create each of param with key-value pair:
<% params[:filters].each do |key,value| %>
<%= hidden_field_tag "filters[#{key}]",value %>
<% end %>
You actually want/need to 'serialize' a hash using hidden fields.
Add this to your ApplicationHelper :
def flatten_hash(hash = params, ancestor_names = [])
flat_hash = {}
hash.each do |k, v|
names = Array.new(ancestor_names)
names << k
if v.is_a?(Hash)
flat_hash.merge!(flatten_hash(v, names))
else
key = flat_hash_key(names)
key += "[]" if v.is_a?(Array)
flat_hash[key] = v
end
end
flat_hash
end
def flat_hash_key(names)
names = Array.new(names)
name = names.shift.to_s.dup
names.each do |n|
name << "[#{n}]"
end
name
end
def hash_as_hidden_fields(hash = params)
hidden_fields = []
flatten_hash(hash).each do |name, value|
value = [value] if !value.is_a?(Array)
value.each do |v|
hidden_fields << hidden_field_tag(name, v.to_s, :id => nil)
end
end
hidden_fields.join("\n")
end
Then, in view:
<%= hash_as_hidden_fields(:filter => params[:filter]) %>
This should do the trick, even if you have a multilevel hash/array in your filters.
Solution taken http://marklunds.com/articles/one/314
I just wrote a gem to do this called HashToHiddenFields.
The core of the gem is this code:
def hash_to_hidden_fields(hash)
query_string = Rack::Utils.build_nested_query(hash)
pairs = query_string.split(Rack::Utils::DEFAULT_SEP)
tags = pairs.map do |pair|
key, value = pair.split('=', 2).map { |str| Rack::Utils.unescape(str) }
hidden_field_tag(key, value)
end
tags.join("\n").html_safe
end
Here's how I managed to pass a parameter value through my view - that is, from View A through View B and on to the controller:
In View A (index):
<%= link_to 'LinkName', {:action => "run_script", :id => object.id} %>
In View B (run_script):
<%= form_tag :action => 'index', :id => #object %>
<%= hidden_field_tag(:param_name, params[:id]) %>
In the controller:
Just reference params[:param_name] to make use of the value.
The key transition that wasn't documented anywhere I could find is where {... :id => object.id} from View A is passed on to View B as <%... :id => #object %>, which View B then passes on to the controller as (:param_name, params[:id]) through the hidden_field_tag construct.
I didn't see this documented anywhere but after perusing several posts across several sites including this post (whose syntax provided the key inspiration), the solution finally gelled. I've seen the caveats on hidden fields pertaining to security but have found no other way to do this given my current design, such as it is.
it's because when you convert in HTML with your hidden_field_tag, the backquote is add. After when you received it like a string not a Hash.
The Hash type can't exist in HTML. You have only string. So if you want pass your hash (not recommend by me), you need eval it when you received it. But can be a big security issue on your application.
As a caveat to Vlad's answer, I had to use raw:
<%= raw hash_as_hidden_fields(:filter => params[:filter]) %>
to get it to work in Rails 3.1.1. Essentially, the text being output was being escaped, eg., "<" becoming "&lt".
Assuming the hash is strings, symbols, numbers, and arrays, you can call eval to convert the params string of the hash from the hidden_fields form back into a hash in the controller. Then the backslash escape characters for the quotes added are no longer an issue:
hash = eval(params["hash_string"].to_s)
Credit to the following article for helping identify this simple solution for my case:
How do I convert a String object into a Hash object?
Keep in mind the contents of the params should be cleaned with .require and .permit.

Resources