Raw and simple_form...neither is perfect - ruby-on-rails

I have this in one of my models:
def rank_match_2
...
...
array = [start, finish, [words]]
results = field.insert(start, "<mark>") and field.insert(finish, "</mark>")
...
end
Now I know I shouldn't be adding view logic in the model, but I am building a search app that has quite a bit of logic built into how the results are rendered. At this point I don't see how to get around including it in the model, so I that's what I am doing.
My problem is this:
On the view, I have this:
<%=raw #parse.rank_match_2 %>
This effectively handles the html "mark" tags inserted in the model logic and DOES highlight the correct text, but DOES NOT include line breaks etc.
However, this:
<%= simple_form(#parse.rank_match_2).html_safe %>
does not handle the 'mark' tags and therefore DOES NOT highlight the correct text, but DOES correctly format the line breaks as expected.
I want to do both: highlight the correct text by inserting the 'mark' tags into the model object (which seems to work with 'raw'), AND render correctly formatted html with line breaks etc.
Any idea what I am missing. I am trying Draper gem but I don't think it is suitable for exactly what I want.

Related

Watir - How do I collect all links where the span contains aria_label "Multimedia"

I have written a ruby code where the browser object finds all links and then I store them one by one in an array if they match a specific regex.
#browser.links.collect(&:href).each do |link|
matches = regex.match(link)
array_of_multimedia << matches[:multimedia_id] if matches
end
I am trying to create a filter where I only iterate over those links where the span inside the second child div contains the aria-label as Multimedia.
Attached is the screenshot of the HTML structure.HTML structure
I tried a few approaches like finding all spans and then going bottom up to the parent's parent of the span but its not giving me the href.
#browser.spans(aria_label: "Multimedia").each do |span|
span.parent.parent.a.hreflang #Didn't work
span.parent.parent.a.link.href #Didn't work
span.parent.parent.href.text #Didn't work
element.tag_name #This shows "a" which is correct though
end
I also tried a top down approach by doing
#browser.links.collect(&:href).each do |link|
link_element = #browser.link(href: link)
link_element.children.following_sibling(aria_label: "Multimedia").present? #Didn't work
end
So far, no luck in getting the actual hrefs. Will appreciate any help!
Because the span is inside the link tag, it's going to be easier to go bottom up
Do as much as you can with the Watir locators rather than multiple loops.
The parent method takes arguments:
#browser.spans(aria_label: 'Multimedia').map {|span| span.parent(tag_name: 'a').href }
As for what you tried:
# parent.parent is the link, so calling `#a` is looking for a link nested inside the link
span.parent.parent.a.hreflang
span.parent.parent.a.link.href
# href should give you a String, you shouldn't need to call #text method on it
span.parent.parent.href.text
# element isn't defined here, but try just element.href
element.tag_name
Also note that Element#href method is essentially a wrapper for Element#attribute_value('href').

Searching for contents between two specified tags

I installed Nokogiri into a Rails project and it can currently run "Nokogiri HTML Parser Example" with no issues.
I'm trying to create a Rails project that will parse a movie script from IMDB, conduct a word count, then display the most occurring words from that section. I've identified that the scripts are kept in a "table":
<table width=100% border=0 cellpadding=5 class=scrtext><tr><td class=scrtext><pre><html><head></head><body>
<b>PERSON1</b>
They say some dialogue
<b>PERSON2</b>
They say some more
</pre></table>
I would like to exclude the text within the <b>/<b> brackets as well.
I've been setting this up like the example above in the controller, and have gotten as far as taking in the URL:
#Save as a temp. file
tmp_file = open('http://www.imsdb.com/scripts/Authors-Anonymous.html')
#Parse the temp. file
doc = Nokogiri::HTML(tmp_file)
I'm having difficulty understanding how to set the CSS constraints to grab this table. I understand that it's between those <pre>/<pre> tags, and I've followed a number of tutorials for this but I still don't understand how to set up those constraints.
I feel that the code following this should be something like this, but I'm not awfully sure:
doc.search("//pre")
How do I set up Nokogiri's CSS constraints to pull the content between two tags such as <pre></pre>, and then filter out irrelevant tags such as <b></b> that will occur within the output?
You can use the css method selector: doc.css('pre b') which will get every <b> tag(s) inside every <pre> tag(s):
doc.css('pre b').each do |b_tag|
# b_tag will be a String containg like `<b>this text is bold</b>`
end
It might not be the most elegant solution but it did the trick for me.
In the controller, I defined the following:`
def index
page = [THE_URL]
doc = Nokogiri::HTML(open(page))
#content = doc.css('b').remove
#content = doc.css('pre')
puts #content
end
and then in the View;
<%=#content %>

How do I send data from a controler to a view in Ruby on Rails

I have a simple controller that was created through a scaffold and has a "Show" function.
In the view that was created through the scaffold, I have an image that appears only on a certain condition.
I want to set or evaluate the condition in the controller and send it to the view.
I am not sure how to do that or whether this is the correct approach.
The condition should generally be dealt with in the view file using erb, or haml. If you update your question with the condition, then I'll see about updating my answer to reflect it. For now, I'll use a common condition.
Say you only want to show an image if an object is featured. Let's imagine there is a featured field in your object that acts as a flag (1,0).
If this object is say an Article, we can then check the condition in the view file. The controller would obtain the article from the model:
-# articles_controller show action
#article = Article.find(params[:id])
..
-# views/articles/show.html.erb
<% if #article.featured? %>
// show image here
<% end %>
Remember this is an example condition that is not necessarily correct. It is just to illustrate my initial approach.
I wouldn't suggest you use javascript to hide/show depending on this condition, because you are then putting your logic in javascript, when it can be easily managed from within your view files.
If the condition is complex, you would then move it to the model, and perform something like:
if #article.some_complex_condition?
..rather than having that complex condition in your controller file. This allows you to reuse the condition away from the specific controller and makes it more testable.
If you just want to show and hide an image based on a certain condition, than you can do that with JQuery. You shouldn't put anything in the controller that is view-centric.
You can also get the id of whatever data element is in 'show' and pass it to the JavaScript.
JQuery has show() and hide() methods that would work for you. Here's the documentation on the hide method: http://api.jquery.com/hide/
Basically, if you had a certain id for your image, you'd do something like this:
$(document).ready(function() {
$("#myImage").hide();
if (some_condition === true) {
$("#myImage").show();
}
});
You can put that code in your application.js file.
I whipped up a simple JsFiddle demonstrating a way to show and hide with buttons:
http://jsfiddle.net/phillipkregg/92RDS/
Of course, the code may be different depending on what you are trying to do.
If you need to get the 'id' of the object in the 'show' view, than you can put a script tag at the bottom of your show view like this:
<script type="text/javascript">
var my_show_object = <%= #some_object.id %> //this will be the specific id of whatever the object is that you passed from the controller
alert(my_show_object); //this helps with debugging to see if you have the right id
</script>
If you need more than the id, and you want to get the entire Rails object and represent it as Javascript - just do this at the bottom of your rails 'show' view:
<script type="text/javascript">
var my_object = <%= #your_rails_object.to_json %>;
console.log(my_object); //This code allows you to look in the console and see exactly what your object looks like.
</script>
Just like the last one, #your_rails_object is the variable that you have in your show view in the controller. This will return it as a json object so that you can get the id or whatever properties it has.
Also, if you are just learning Rails, I would recommend this online book: http://ruby.railstutorial.org/ruby-on-rails-tutorial-book
That's how I learned Rails - the book is excellent and free.

Parsing a 'template' in rails (alternatives to gsub)

I have a 'template' system in my CMS rails app. Basically the whole HTML template is stored in a database column and it has key code in the string (like <!--THEME_Body-->) that gets replaced with content generated by the application.
I use an actual layout to render the template. All that is in the layout is:
<%= generate_theme.gsub!('<!--THEME_Body-->', yield) -%>
That helper takes the correct theme and further gsubs other area like Meta data and Breadcrumbs.
I'm just wondering if there's a better way to go about this? Perhaps using content_for or something like that?
That's a pretty good way of going about it, although I would make use of Ruby's sexy syntax to combine all the lines into something a little more syntactically correct - it speeds the script up and it looks a damn sight nicer too!
tags = {
'<!--THEME_Body-->' => yield,
'<!--THEME_Head-->' => yield(:head),
'<!--STYLESHEET-->' => stylesheet_link_tag('application')
}
tags.each { |str, rep| generate_theme.gsub!(str, rep) }
Bear in mind that this code should not go in a view - it should ideally be put in a model, as it's to do with the application's data, but it could also go in a helper somewhere. If it's an instance variable in a model, you could just call
generate_theme.parse
And that code could be executed - it looks a lot better and sticks to the standard MVC convention of cleaning up the view as much as possible.
Jamie

Keyword searching defaulting to AND

I successfully installed and set it up searchlogic for basic (keyword) searching. I have the following problem:
#search = Proposal.search(params[:search])
#proposals = #search.all
The above code works properly if I type in a keyword such as "red". It will bring up everything with red keyword. Or if I type in "green", it will bring up everything with green as a keyword. However, when I type "red green" in the search box it will ONLY bring up cases where the keywords are BOTH red and green (and not bring up instances where they may only have one of the two keywords). Yes, I am using keywords_like_any. I can see what the general problem is via debug, keywords_like_any: green red. The below code works as I want it to (bring up any instances of red OR green).
#search2 = Proposal.keywords_like_any("red", "green")
#test = #search2.all
I believe what I need to do to solve the issue is turn the first code to view params[:search] as an array? I tried doing params[:string].to_s.split (as shown in railscast) however it did not work.
The *_like_any is intended to be used with checkboxes form helpers (f.check_box) which outputs arrays into your params hash as opposed to f.text_field which outputs strings. If you still want to use them with a f.text_field you can :
split the field with Javascript on client side to output an Array
split it in your controller
Considering that your field is named keyboard here is some code that should solve your problem :
params[:search][:keywords_like_any] = params[:search][:keywords_like_any].split(' ')
#proposals = Proposal.search(params[:search])
You can skip the line #proposals = #search.all because search results works like an array.
You said you tried params[:string].to_s.split - I don't know if that's a typo, but it should be params[:search].to_s.split
I may not understand your question, but it appears to me that you're trying to implement something in the controller that belongs in the view. If your view has this:
- form_for #search do |f|
= f.text_field :color_like_any
then your initial controller example will work.

Resources