Trying to come up with a more compact way of expressing this conditional in HAML and Ruby, perhaps with a ternary operator:
- if #page.nil?
%br (nothing yet)
- else
%br #{#page.name}
(looking for similar approach as per Neat way to conditionally test whether to add a class in HAML template)
Your help would be appreciated :)
The code you have makes the text a child of the <br> element; that is not desirable. What you really meant, I think, was:
%br
- if #page.nil?
(nothing yet)
- else
#{#page.name}
For this you can simply do:
%br
#{#page.nil? ? "(nothing yet)" : #page.name}
Or
%br
= #page.nil? ? "(nothing yet)" : #page.name
Or simply:
<br>#{#page ? #page.name : "(nothing yet)"}
However, personally I would 'fix' this in the controller so that you always have a #page, with something like:
unless #page
#page = Page.new( name:"(nothing yet)", … )
end
With this you can stub out what a new/empty/nothing page looks like and let your view treat it like any other. Your #page still won't have a #page.id, so you can use that for tests to decide if you are creating a new item or editing an existing one.
This is how I handle all my forms that may be used to create or edit an item: provide defaults by creating (but not adding to the database) an item with the default values.
Aside: You're creating a <br> which is almost never a good idea, and you're creating it with Haml which should not be used for content markup. You might step back and think about what you're doing.
Simply do:
%br
= #page.try(:name)
You can also embed in a string
assuming - order_count = 12:
%h5= Ordered #{ order_count == 1 ? "1 item" : "#{order_count} items" } for this session
%br = #page ? (nothing yet) : #{#page.name}
Related
I'm using this http://www.xpathtester.com/xpath/5a30592045b6aa5089faf909261ede0b XPath tester, which returns exactly what I want. For some reason it removes my full query, but if you use it, it works.
*/h3[contains(string(), "Description")]/following-sibling::p[1]
But in real life, I get nothing from my variable.
I'm trying to get the data after <h3>Description</h3>, in this case a paragraph <p>.
HTML
$feed_item=
<div class="outer-feed"><ul>
<li><strong>Severity:</strong> <span class="label label-info">Low</span></li>
</ul>
<h3>Description</h3>
<p>The lack of validation of configuration parameters used in SQL queries caused various SQL injection vectors.</p>
...
Here's my XPath
$description_node = $xpath->query('*/h3[contains(string(), "Description")]/following-sibling::p[1]', $feed_item);
$description = "description: " . $description_node->item(0)->textContent;
and var_dump
object(DOMNodeList)#1654 (1) { ["length"]=> int(0) }
And the error
Notice
: Trying to get property 'textContent' of non-object in
What confuses me is that I can get Severity from the same HTML by using this:
$severity_node = $xpath->query('*/li[contains(string(), "Severity:")]', $feed_item);
$severity = preg_replace('/Severity:\W*/u', '', $severity_node->item(0)->textContent);
My first thought was to scale back to just the H3 and output that.
$description_node = $xpath->query('*/h3[contains(string(), "Description")]', $feed_item);
object(DOMNodeList)#1654 (1) { ["length"]=> int(0) } // doesn't contain anything
Given that the following are identical but the first works and the second doesn't, what could be the problem?
$severity_node = $xpath->query('*/li[contains(string(), "Severity:")]', $feed_item);
$description_node = $xpath->query('*/h3[contains(string(), "Description")]', $feed_item);
Why is one working and not the other. And what is the best way to troubleshoot things like this. It seems to work on the xpathtester. What could I be doing wrong that causes this problem in PHP?
Try with this XPath:
//h3[text()="Description"]/following::p[1]
A query starting */h3[...] will only work if the context item when it is invoked is the grandparent of the h3 element. You've given no information about the context item, so I suspect it is something different.
You ask the question(s): "Why is one working and not the other. And what is the best way to troubleshoot things like this. It seems to work on the xpathtester. What could I be doing wrong that causes this problem in PHP?"
Well, the first thing is to understand that XPath expressions may depend on the context item, and that the same expression evaluated with different context items is going to give different results. Once you understand that concept, it hopefully becomes a lot clearer.
My question model holds the prompt and the answer choices for questions that students can answer. It includes columns named :choice_0, :choice_1, :choice_2, :choice_3, :choice_4, and :choice_5.
In one section of my controller, I've used the following code:
correct_array.push(these_params[:choice_0]) if !these_params[:choice_0].blank?
correct_array.push(these_params[:choice_1]) if !these_params[:choice_1].blank?
correct_array.push(these_params[:choice_2]) if !these_params[:choice_2].blank?
correct_array.push(these_params[:choice_3]) if !these_params[:choice_3].blank?
correct_array.push(these_params[:choice_4]) if !these_params[:choice_4].blank?
correct_array.push(these_params[:choice_5]) if !these_params[:choice_5].blank?
In other areas of my app, I've used the #{} syntax, for example:
params[:choice_#{n}]
But that doesn't work within a params hash for some reason. I'm sure that there is a drier way to accomplish these five lines.
Thank you in advance for any insight.
A more Ruby way to do this is:
correct_array = (0..5).map { |i| these_params["choice_#{i}".to_sym] }.select(&:present?)
Or as a method:
def correct_array
(0..5).map { |i| these_params["choice_#{i}".to_sym] }.select(&:present?)
end
In either case, you have the added bonus of not having to initialize correct_array as it is created on the fly.
You may try this
(0..5).each do |i|
param_i = these_params["choice_#{i}".to_sym]
correct_array.push(param_i) if param_i.present?
end
I tried meta_search, but after adding "include MetaSearch::Searches::ActiveRecord" into my model, it raised an error as "undefined method `joins_values'" when run "MyModel.search(params[:search])"
I think I dont need full text, so I think following gems are not suitable for my project now::
mongoid_fulltext
mongoid-sphinx
sunspot_mongoid
mongoid_search
I tried a old gem named scoped-search
I can make it work for example:
get :search do
#search = Notification.scoped_search(params[:search]
search_scope = #search.scoped
defaul_scope = current_user.notifications
result_scope = search_scope.merge defaul_scope
#notifications = result_scope
render 'notifications/search'
end
but it will be allow to call any scopes in my model.
Is there any "best practice" for doing this job ?
If you want limit the scope you want use on your scoped_search you can filter your params[:search] like :
def limit_scope_search
params[:search].select{|k,v| [:my_scope, :other_scope_authorized].include?(k) }
end
.row
.nine.columns.centered
%ul.bucketlist
- #buckets.each_with_index do |resource, index|
%a{:href => "#{bucket_path(resource)}"}
%li.bucket
%h4= index + 1
%h5= resouce.name
%a{:href => "#{new_bucket_path}"}
%li.bucket.empty
= image_tag "add.gif"
%h5 Add Bucket
I have the above code written in 3 different views, with only minor differences between them. This doesn't seem very DRY to me, so I'm looking for some help to clean this up.
Between the views only a few things vary:
#buckets.each - The #buckets collection needs to change between #notes, #units aswell.
#{bucket_path} - I'd like to be able to pass in a variable so that bucket_path becomes resource_path.
If anyone can offer any help, it'd be much appreciated.
My experience with haml is limited, but I think you should be able to put the common code into a partial (a file named _common.html.haml, for instance), and then in the view simply do:
= render 'common', :items => #buckets, :new_item_path => new_bucket_path
Then change the partial like this:
%ul.bucketlist
- items.each_with_index do |resource, index|
%a{:href => url_for(resource)}
%li.bucket
%h4= index + 1
%h5= resouce.name
%a{:href => "#{new_item_path}"}
%li.bucket.empty
= image_tag "add.gif"
%h5 Add Item
One solution could be writing a helper function to generate the html.
People typically don't like html in helpers, but in this case it
would be a good idea. Write a function where you pass in the resource
name and it generates this code for you
Another way is to check the controller you are in and generate the required code based on that. For instance
resource = #buckets if params[controller]=='bucket'
A more condensed way to remove if statements would be something like following, but i havnt tried it out.
exec "resource = ##{params[:controller]}s"
Let me know if you need more help.
I have a collection of objects. There are 3 properties in each object
'id', 'name', 'is_primary'
The collection of objects will usually have anywhere from 1 to 5 objects.
What I want to do is check the collection to see if is_primary is true. If so output the name, or at least return it.
I want to do this in 1 line of code if possible. I am trying to slim up this one line for erb output in rails. Later in the page i'll output them all. I thought I had it, but if I return nil it adds extra space which shifts all the html oddly.
Thanks.
Hmm, this doesn't quite work if no element is_primary...I'm still thinking...
c.detect(&:is_primary).name
Ok, how about:
((a = c.detect(&:is_primary)) && a.name).to_s
As it happens, it is OK in an erb template for the <%= expression to return nil, that just results in an empty string, so for that case you can use:
(a = c.detect(&:is_primary)) && a.name
Update: Responding to the first comment, I do have a test case that I didn't post...
class A; attr_accessor :is_primary, :name, :id; end
t = [A.new, A.new, A.new, (a = A.new; a.name = 'xyz'; a.is_primary = true; a)]
puts (a = t.detect(&:is_primary)) && a.name
puts ((a = [].detect(&:is_primary)) && a.name).to_s
Complementing #DigitalRoss, you can also write:
collection.detect(&:is_primary).try(:name) || "default_if_no_element_or_name"
(well, to be honest I prefer Ick's maybe over Rails' try: c.detect(&:is_primary).maybe.name)
Side note: IMHO a flag that can only be active for a row it's not such a good idea. You may have inconsistent states with more than one being active and you'll have worry about it when updating (transactions, and so on). Try to store the PK reference somewhere else (a parent model? a state model?).
I want to do this in 1 line of code if possible. I am trying to slim up this one line for erb output in rails. Later in the page i'll output them all.
No need for one-liners (funny since I just wrote one): move the code to yous models or helpers as appropriate and keep your views pristine.