Reading up here I find that I can use the simple_format text helper to send a text string to keep html newlines. Great. But I find that since it assumes a tag that it messes with the CSS class in Blueprint CSS. OK, reading up on the API I find this:
simple_format(text, html_options={}, options={})
simple_format("I'm allowed! It's true.", {}, :sanitize =>
false)
=> "I'm allowed! It's true."
There's no other example using an html_option that I can find. Here are two attempts to make it work, but both fail, either with syntax errors or app errors.
<
%=simple_format(#opening.bob, html_options={"class="base prepend-1""},
:sanitize => false) %>
true) %>
I've tried a bunch of fooling around with different combinations but due to my inexperience, I'm not hitting the right one. What am I not seeing? thanx, sam
While I still haven't gotten this to work using html options, I failed to see the relevance of the example above it:
simple_format("Look ma! A class!", :class => 'description')
=> "Look ma! A class!"
It was pointed out to me that this is a hash and the class indicated is a CSS attribute, not a Rails attribute.
'base prepend-1') %>
using my variables above.
Related
So this is ruby right, and while I do have a solution already, which I'll show below, its not tight. Feels like I'm using ahem "C++ iterators", if you will. Too many lines of code. Not like ruby.
Anyway, I'm wondering if there is classier way to do this:
b = Watir::Browser.new
b.goto "javascriptinjectedtablevalues.com" #not real website url:)
# desired urls in list are immediately located within <span> tags with a "class" of
#"name" plus a custom html attribute attribute of "data-bind" = "name: $data". that's it
# unless I wanted to use child-selectors which I'm not very good at
allrows = b.spans(:class => "name").each_with_index.map do |x, i|
[0, x.attribute_value("data-bind")]
end
real_row_ids = allrows.select{|i, databind| databind == "name: $data" }.map(&:first) #now I have all correct span ids
spans = real_row_ids.map {|id| b.spans(:class => "name")[id] }
Now that's a little messy in my opinion. But it leaves artifacts so I can debug and go back and stuff.
I could use this command to just grab a just the spans
spans = b.spans(:class => "name").map do |span|
[span, span.attribute_value("data-bind")]
end.select {|span, databind| databind == "name: $data"}.map(&:first)
but that still feels messy having no artifacts to show for it to use for later when trying to isolate other html tags nearby the span.
I'm hoping there is something like this pseudo code for watir:
b.spans(:class => "name").with_custom_attributes(:key => "data-bind", :value => "name: $data")
that's what I'd really like to do. superman-patching this custom method onto Watir within a rails initializer would be the optimal solution second to it already existing within Watir!
Watir already supports using data attributes for locators. You simply need to replace the dashes with underscores.
For example:
b.spans(:class => 'name', :data_bind => "name: $data")
Would match elements like:
<span class="name" data-bind="name: $data">
Similarly, you can use a regex when matching the data attribute:
b.spans(:class => 'name', :data_bind => /name/)
Now, this is my HTML,
<div class = 'div-of-all-names'>
<div class='best-first-name'>
<span itemprop='name'> Alexander </span>
</div>
</div>
I have this hash in my Ruby Program,
URL = "http://www.xxx.com/xxxxxxxxxxxxxxxx/xxxxxxxxxxx/xxxxxxxx"
agent = Mechanize.new
page = agent.get(URL)
patterns = {1 => ['at("div.div-of-all-names")'],
2 => ['at("div.best-first-name")'] ,
3 => ['search("span[#itemprop='name']")']}
# Selecting those keys that is a number and sorting
p = patterns.keys.select{|i| /[0-9]/ =~ i.to_s }.sort
# p = [1,2,3]
p.each do |i|
p[i].each do |j|
out = page.send(j)
if !(out.blank?)
page = out
p j
break
end
end
end
name = page.inner_text
p name
Questions:
1. Can I not use ruby's "send" on a Nokogiri object?
Because, I can use the ruby hashes and store the actual "search" or "at" with the "class", "id" ,"itemprop" or whatever html attributes in the hash as levels, 1,2 and 3.
Once they are stored as levels, I will retrieve from them as loop variables in "i" or "j" and use a ".send(j)" on the Nokogiri Objects.
I tried this and got this error,
1.9.3p385 :238 > a
=> "at(\"div.our_price\")"
1.9.3p385 :239 > page.send(a)
NoMethodError: undefined method `at("div.our_price")' for #<Mechanize::Page:0xb2ba6dc>
from (irb):239
2. If Im using "at", can I only manipulate classes? Like,
"page.at('span.humble')"
**means**
<-span-class ='humble'>
Humble
<-/-span>
**then what about**
<-span-id='humble'>
Humble
<-/-span>
You need to give the method name and parameters to send separately:
obj.send("methodname", "arg1", "arg2")
If Im using "at", can I only manipulate classes?
"page.at('span.humble')"
**means**
<-span-class ='humble'>
Humble
<-/-span>
**then what about**
<-span-id='humble'>
Humble
<-/-span>
OK, first, don't make up ways to highlight your HTML. Use normal formatting and plain-old HTML and, if necessary, put it into a separate section, otherwise you'll confuse us and someone will tell you the problem is invalid HTML. It should look something like this in your question at a minimum:
page.at('span.humble')
means:
<span class ='humble'>
Humble
</span>
then what about:
<span id='humble'>
Humble
</span>
With that out of the way...
Why would you think that you can't use IDs? You're defining a CSS accessor, so use one for ID:
page.at('span#humble')
at, like search, is not limited to classes or IDs. If you can define it as CSS (including lots of jQuery extensions), then Nokogiri should be able to find it. Nokogiri also supports XPath accessors so you can jump between the two styles as needed to pinpoint the node you want.
I recommend CSS because it's generally cleaner and less noisy. You can use either with at and search, even though you'll often see people use the more explicit at_css and at_xpath or css and xpath instead of search. I'm lazy and only use the more generic versions.
I highly recommend spending some time perusing Nokogiri's documentation. It's very powerful and allows you to munge HTML/XML all day long.
It seems that you're setting these up for instance_eval rather than send:
page.instance_eval 'at("div.div-of-all-names")'
I'm updating my rails 2 apps to rails 3 and find that the use of 'render :text' does not behave the same anymore.
#results is an array. In my controller:
render :text => "<ul>#{#results}</ul>"
It's returning the whole array as a string rather than iterating through each value:
<ul>
["
<li>Steve</li>
", "
<li>John</li>
"]
</ul>
Worked fine in Rails 2.x but not in 3. How do I fix this?
I'm expecting a result of:
<ul>
<li>Steve</li>
<li>John</li>
</ul>
I know this question is for Rails 3.1.4 only.
But those who come here and are on a more recent version, starting with Rails 5.1 we'll do this:
render plain: "I'm like everyone else."
The string contains HTML tags so you will need to mark it as safe so that Rails doesn't escape the tags.
render :text => "<ul>#{#results}</ul>".html_safe
NOTE: Unless there is a valid reason to have HTML in your controller, I recommend moving the list items to a view.
6/23/2014 UPDATE: In retrospect, I don't like having this string parsing logic in the controller. The #results suggests there is HTML embedded in an object somewhere. I recommend using a presentation object and call a method like #results.list. The Draper gem is well-suited for this.
Cite
https://github.com/drapergem/draper
I would suggest doing the following instead of render :text
render :partial => "result", :collection => #results
and add the file: _result.html.erb with
<ul>
<%= result %>
</ul>
or even better if you can remove the li tags from #results
<ul>
<li><%= result %></li>
</ul>
The Rails 3 docs say render text should be used for NON HTML text, which does not fit your use case. Using render :partial :collection is a better and more rails 3 way to iterate through your list.
is it possible to add html-content inside a link_to helper in HAML?
i tried this, but all i get is a syntax error:
= link_to "Other page", "path/to/page.html"
%span.icon Arrow
expected output:
Other Page<span class="icon">Arrow</span>
You should use block
= link_to "path/to/page.html" do
Other page
%span.icon Arrow
If anyone is still using Rails 2.x on a project, it looks like the accepted answer returns the block, thus duplicating the link in the markup. Very simple change: use - instead of =
- link_to "path/to/page.html" do
Other page
%span.icon Arrow
The simplest way to do it is by using html_safe or raw functions
= link_to 'Other Page<span class="icon"></span>'.html_safe, "path/to/page.html"
or using raw function (recommended)
= link_to raw('Other Page<span class="icon"></span>'), "path/to/page.html"
Simple as it can get !!
Don’t use html_safe method unless you’re sure your string isn’t nil. Instead use the raw() method, which wont raise an exception on nil.
Clarification: The creator of the post should be able to decide when the truncation should happen.
I implemented a Wordpress like [---MORE---] functionality in my blog with following helper function:
# application_helper.rb
def more_split(content)
split = content.split("[---MORE---]")
split.first
end
def remove_more_tag(content)
content.sub(“[---MORE---]", '')
end
In the index view the post body will display everything up to (but without) the [---MORE---] tag.
# index.html.erb
<%= raw more_split(post.rendered_body) %>
And in the show view everything from the post body will be displayed except the [---MORE---] tag.
# show.html.erb
<%=raw remove_more_tag(#post.rendered_body) %>
This solution currently works for me without any problems.
Since I am still a beginner in programming I am constantly wondering if there is a more elegant way to accomplish this.
How would you do this?
Thanks for your time.
This is the updated version:
# index.html.erb
<%=raw truncate(post.rendered_body,
:length => 0,
:separator => '[---MORE---]',
:omission => link_to( "Continued...",post)) %>
...and in the show view:
# show.html.erb
<%=raw (#post.rendered_body).gsub("[---MORE---]", '') %>
I would use just simply truncate, it has all of the options you need.
truncate("And they found that many people were sleeping better.", :length => 25, :omission => '... (continued)')
# => "And they f... (continued)"
Update
After sawing the comments, and digging a bit the documentation it seems that the :separator does the work.
From the doc:
Pass a :separator to truncate text at a natural break.
For referenece see the docs
truncate(post.rendered_body, :separator => '[---MORE---]')
On the show page you have to use gsub
You could use a helper function on the index page that only grabs the first X characters in your string. So, it would look more like:
<%= raw summarize(post.rendered_body, 250) %>
to get the first 250 characters in your post. So, then you don't have to deal w/ splitting on the [---MORE---] string. And, on the show page for your post, you won't need to do anything at all... just render the post.body.
Here's an example summarize helper (that you would put in application_helper.rb):
def summarize(body, length)
return simple_format(truncate(body.gsub(/<\/?.*?>/, ""), :length => length)).gsub(/<\/?.*?>/, "")
end
I tried and found this one is the best and easiest
def summarize(body, length)
return simple_format = body[0..length]+'...'
end
s = summarize("to get the first n characters in your post. So, then you don't have to deal w/ splitting on the [---MORE---] post.body.",20)
ruby-1.9.2-p290 :017 > s
=> "to get the first n ..."