ActiveSupport::SafeBuffer not rendered in view? - ruby-on-rails

Very simple question really, but it's driving me nuts.
I have this method call in a Rails view:
<%= get_image(#document) %>
The method in here returns an object of type ActiveSupport::SafeBuffer. If I call .to_str on it in a console, I see the expected result (just an html img tag). However, when I stick the above code in a view, there's nothing there. Just an empty string.
If I do this:
<%= get_image(#document).to_str %>
in an effort to convert the SafeBuffer into a String object, I see the literal HTML in the page, and not the image tag.
I feel like I'm missing something simple or elementary here. Can anyone point the way? Thanks in advance!
EDIT: since it's been requested, here's what the get_image method looks like:
def get_image(document)
document[document.type+'.image'].nil? ? nil : document[document.type+'.image'].as_html_safe
end

Related

Rails - return html black from model

I have a method in my model which is called in a modal like this:
<div class="col-sm-9"><%= #notification.notifier_context %></div>
In this method, I want to return some HTML like this, which has a rails helper path in it.
context = "<td><%= link_to('link', account_item_path(#item.account, #item))%></td>".html_safe
But its just out-putting the string as is. How can I get it evaluated to HTML proper?
Thanks
Try:
"<td>#{link_to('link', Rails.application.routes.url_helpers.account_item_path(#item.account, #item))}</td>".html_safe
String is not erb template so you can't use <%= %> syntax.
Also it's great idea to use helpers (with content_tag) or partials for that.
Also if you need to use routes inside model class, read following answer.

Elegant way to show corresponding text_field_tag value in Rails 4

So my problem is showing something that a model has in a nice and simpler way.
So what currently works?
In my viewer this works fine:
<%= text_field_tag(:first_name, (current_user.present? ? current_user : '').first_name.present? ? current_user.first_name : '') %>
However this is too long and really hard to maintain, especially when I have several more fields.
So to avoid that I made this in my controller
def user_vals(value)
if(current_user.present?)
current_user.value.present? ? current_user.value : ''
end
return ''
end
Within this controller I can call user_vals(:first_name) but get undefined methodvalue'` error. Furthermore I cannot just call
<%= text_field_tag(:first_name, #user_vals(:first_name)) %>
As I am getting some syntax error with brackets but that's not the real issue.
So my ultimate goal is to have something like this:
<%= text_field_tag(:first_name, #user_vals(:first_name)) %>
Rather than the first code I've given above. How can I achieve that?
You can use try in this case. Just write:
<%= text_field_tag(:first_name, current_user.try(:first_name)) %>
See: http://apidock.com/rails/Object/try
I would recommend to take a step back and try to use Duck Typing to solve this...
What you have right now is a current_user method. This method can return whatever object it wants if the user is not logged in, and that object can respond to whatever it wants. Here's a simplified example:
def current_user
#user || OpenStruct.new(first_name: "")
end
Note: I'm assuming #user holds the currently-signed in user... but this may be a call to super instead, or whatever else depending on your implementation.
So now, instead of branching based on what type of object is coming back from the current_user method, you can now just use the returned object without regard.
current_user.first_name # => Either the User object's first name or `""`
You can go further with this by creating e.g. a GuestUser class and having GuestUser.new returned instead of the OpenStruct above. Guestuser would be a model that is not data-base backed and could respond to any number of methods as needed.
This idea has been represented by many others as well. And using a class to prevent repeated code switching based on nil actually has a name: The Special Case Pattern. As a quick, free example, see the Guest User RailsCast. Or, if you subscribe to Ruby Tapas, be sure to check out episode 112: Special Case. This topic, and many others, are also covered in depth in Avdi Grimm's excellent book: Confident Ruby, which I highly recommend.

Return html from method

I'm attempting to return HTML straight from a model method to show the last reply to a Topic.
My Topic model:
class Topic < ActiveRecord::Base
has_many :replies
def last_reply
self.replies.last.name
end
end
and the view:
<%= topic.last_reply %>
It renders HTML with speech marks around it indicating a string. How do I get rid of these speech marks?
My thought:
def last_reply
self.replies.last.name.html_safe
end
I'm scared of doing this incase someone has embedded JavaScript or something as a reply name. I have validations to stop this, but I still want to be doubly-safe. If embedded JavaScript was to be displayed, I would obviously want it literally displayed on the page and not processed by the browser. Does html_safe do this?
Should I be doing this in a decorator or helper? I feel ERB tags should never have 'programming' in them as they should simply contain one method call to display information:
view:
<%= decorate_last_reply %>
decorator:
def decorate_last_reply
model.last_reply #=> "Yep a string I am"
end
I still want to know how I should be returning HTML without those speech-marks. I could probably use the .gsub() method to get rid of them, but I want to know how to do it properly.
Logically topic.last_reply should return the last record - an object. You could do that by scoping or method. Then I would pass it to helper or just create a helper topic_last_reply with getting topic.last_reply and partial rendering

Helper method with the same name as partial

I have a helper with a method named search_form like this:
module Admin::BaseHelper
def search_form(*args)
# my great code here
end
end
To call this method in my HAML code, I can do this:
= search_form
= search_form()
= search_form(param1: "value1", param2: "value2"...)
My problem is with this first call. When I do this in any HAML file, it renders my helper. Except if my file name is _search_form.html.haml. Is that case, it returns nil.
If I put a raise error in the helper, I notice that my method isn't being called, but I am not able to find what is being called and why.
If I use the syntax on the second and third lines, it works as expected by calling my helper method.
So my question is: is this standard Rails behavior or a bug?
By default, Rails will look for a local variable with the same name as your partial, which may conflict with existing method names.
One way to get around this is to simply redefine the method inside your partial:
<% search_form = self.search_form %>
# Rest of the partial's code

Extra instance variable in controller is nil in view?

I have been searching through Stack Overflow for a few hours now, but none of the related questions seem to apply to my issue.
I am new to Rails, with this being my first real project, and I may be confusing the MVC setup a little. I am attempting to assign the #stars instance variable while in an action of the searches_controller.rb:
def create
#search = Search.new(params[:search])
tempstr = searchstr(#search)
#stars = Star.where("tempstr", :limit => 100)
end
#search is created fine, being a complex search with varying parameters. tempstr is just a simple string container for the results of searchstr(#search), which is a quick method for converting the search parameters into a MySql-relevant string (which seems to be easier than trying to use the .where helper normally, in this case). I'm sure I can just put searchstr(#search) directly into the .where, but I split them up for now so I can inspect the elements as they pass through.
Anyways, the issue comes up when I try to call #stars in the show.html.erb view. Even with something as simple as this:
<% #stars.each do |star| %>
<%= display stuff %>
<% end %>
I get an error saying 'each' is not a method of nil:NilClass. So, I changed it to the following to see if #stars was nil:
<%= #stars.inspect %>
Sure enough, #stars is nil. However, when I add this line to my controller to check #stars there:
return render #stars.each
I see that the variable is filled with the correct star objects from the Star.where(), just as I had intended. A quick .inspect shows the variable is not nil, when in the controller.
So, I am unsure why the view is receiving it as nil if it has been defined in the controller just fine. I wouldn't be surprised if it was me misunderstanding how MVC works, though. The Star class was defined in the Star model, but maybe it is because I am trying to access it from the Searches controller, and thus it isn't initialized for the view?
Should I be going about doing this some other way? I attempted to use a local variable (using stars instead of #stars), but then the view says "Undefined local variable or method 'stars'".
Any help would be much appreciated, I have already wracked my brain for hours creating the complex search and parsing the star file data into the database, so I'm a bit burnt out. I can supply more information if requested, I'm not sure what else would be helpful in providing an answer.
You are setting #stars in the create method, but the view you are talking about is show.html.erb. Try setting #stars in the show method too. Something like this:
def show
#search = Search.find(params[:id])
tempstr = searchstr(#search)
#stars = Star.where("tempstr", :limit => 100)
end
If this does not help you, please show the rest of you controller actions, so we can help you better.

Resources