What is wrong in this ruby statement? - ruby-on-rails

I am trying to do something when I am connecting to my own server(local).
I found request.env from the website, so I am using that array to compare my IPs.
<%
if request.env['HTTP_HOST']!="127.0.0.1"
puts request.env['HTTP_HOST']
else
puts "its Local!"
end
%>
When I run above in rails3, I get nothing printed...
I am new to ruby&rails3..

When you want output in the web page, use <%= %>, not <% %>. The output will be the return value of the expression, so you don't want puts.
<%=
if request.env['HTTP_HOST']!="127.0.0.1"
request.env['HTTP_HOST']
else
"its Local!"
end
%>
Note that you can also use the local? method instead of checking environment directly.
<%=
if request.local?
"its Local!"
else
request.env['HTTP_HOST']
end
%>
If you like conciseness you can do it as one line:
<%= if request.local? then "its Local!" else request.env['HTTP_POST'] end %>
For even more view conciseness, make use of a helper method:
<%= ip_or_local %>
where in the matching view helper you put:
def ip_or_local
if request.local?
"its Local!"
else
request.env['HTTP_HOST']
end
end
For this simple case, it may be overkill but in general when you start seeing lots of code in your view, it's time to think about hiding certain things in helpers.

puts will write to the server in this case, not to the response. so you should look for your message in the log of the server.

Do you want to print to the log or to the view?
It might be clearer if you break things up into seperate erb tags.
<% if local? %>
<%= "Text for local" %>
<% else %>
<%= "Text for remote" %>
<% end -%>
You need to use <%= %> tags for lines you want printed and <% %> tags for lines that you want logic in, like conditionals.
If you're new to rails, you should check out the peepcode rails from scratch videos, they're pretty cheap and a lot of rails developers built their base on what's in them. Railscasts are also snack sized little tutorials that will easily get you through a lot of the basics.
Recommended reading:
RUBY:
The ruby pickaxe
The ruby way
Rails:
The Rails way
Head first ruby on rails
Hope I was of some help.

Related

Best way to fix undefined method

I am building a rails app where I have a museums page which has a feature where it displays the museum with the most exhibits. The problem is that when there are no exhibits added to the db it gives an undefined method 'museum_name'. So the problem I have is I am not sure what would be the best way to make a check that would still allow me to access the page if there are zero exhibits?
Museums controller:
def index
#museums = Museum.all
most_exhibits = Exhibit.most_exhibits
most_exhibits.each do |museum|
#top_museum = MuseumsHelper.get_museum_name(museum.museum_id)[0]
end
Helper class method being used:
def self.get_museum_name(museum_id)
Museum.where(id: museum_id)
end
Display in views:
<%= #top_museum.museum_name %>
The best way to do it depends on how you want it to be. I think the ideal solution for yours is to check if/else then show the content accordingly:
<% if #top_museum.present? %>
<%= #top_museum.museum_name %>
<% else %>
<span>Nothing to display</span>
<% end %>
Or using try <%= #top_museum.try(:museum_name) %> or if you have ruby 2.3.0 or newer you can use safe navigation operator <%= #top_museum&.museum_name %> (Read more).
You could use try in your helper, that way it tries the query, if it fails then it returns nil
def self.get_museum_name(museum_id)
Museum.try(where(id: museum_id))
end
Ref: https://apidock.com/rails/v3.2.1/Object/try

Why defined?(var) is not recommended way to test optional locals in views

According to the Rails API,
If you need to find out whether a certain local variable has been assigned a value in a
particular render call, you need to use the following pattern:
<% if local_assigns.has_key? :headline %>
Headline: <%= headline %>
<% end %>
Testing using defined? headline will not work. This is an implementation restriction.
But when I tested it in my Rails projects, the defined? test worked just fine.
Could anyone explain, what exactly the restriction is and when it gets triggered?

If else statements in .html.erb in views

In rails, I often run into the situation where inside the views I'll do something like
<% if #some_condition_previusly_established_in_a_controller %>
<div class="one">123</div>
<% else %>
<div class="two">something else</div>
<% end %>
It looks a bit cluttery. Is this an acceptable way of working with views or not?
Unless you can think of a way to re-write this as a helper method, you're basically stuck with it looking kind of ugly. That's just how ERB is, as it was intended to be a minimal way of injecting Ruby into an otherwise plain-text template, not as something necessarily streamlined or elegant.
The good news is a syntax-highlighting editor will usually make your <% ... %> ERB blocks look visually different from your HTML so that can dramatically improve readability.
It's also why other representations like HAML have been created where that syntax is a lot less cluttered:
- if some_condition_previusly_established_in_a_controller
.one 123
- else
.two something else
For one or two such conditional logic in your views, I guess its fine but when your code gets bigger and you have multiple if..else..end and looks "cluttery", I think you should look at implementing "Presenter Pattern" which greatly cleans up your views by separating your logic to Presenters.
Here is a great tutorial I followed from Ryan Bates in his Rails Casts series on "Presenter Patterns from scratch". http://railscasts.com/episodes/287-presenters-from-scratch.
Have you tried?
<% #some_condition_previusly_established_in_a_controller ? <div class="one">123</div> : <div class="two">something else</div> %>
If your view contains lots of tags and HTML elements, you can put them into partials and logic into model
View:
<%= render :partial => #model.status %>
<%= render :partial => "file/path/#{#model.status}" %> # if your partial is in some different folder
If your status is one, then it would render the file _one.html.erb
If it is two, then it would render the file _two.html.erb automatically.
Model:
def status
if #some_condition
"one"
else
"two"
end
end
Yes, that is the standard (and yes, it looks cluttery).
If you're looking for a possibly cleaner alternative, check out: Conditional tag wrapping in Rails / ERB
You can always move the logic to the controller and leave the view clean(er).
Controller:
if #some_condition
#div_class = :one
#div_content = 123
else
#div_class = :two
#div_content = 'something else'
end
View:
<div class="<%= #div_class %>"><%= #div_content %></div>
Or using a helper:
<%= content_tag :div, #div_content, class: #div_class %>

Highly conditional Rails 3 views

I've got a Rails 3 application where I'm using quite a few conditional statements to change the design of the page. What is the best practice for keeping the logic out of the view for having such drastic amounts of conditionals?
Hypothetical Example:
<% unless #ethos.blank? %>
<%= unless #work.nil? do %>
<%= link_to "Add Work", work_path %>
<% end %>
<%= #ethos.tagline %>
<% end %>
I've got many more conditionals inside of other conditionals. What is the best way to manage this inside of one view?
You should avoid complex conditionals (and most conditionals) in views. Extract them to a Helper, or better yet, to some kind of "presenter" so that you can work with a receiver instead of those "global looking/feeling helpers"
SomeHelper
module SomeHelper
def work_link
(#ethos.present? && #work) ? link_to("Add Work", work_path) : nil
end
end
View
<%= work_link %>
<%= #ethos.tagline if #ethos.present? %>
If #ethos is likely to be nil as opposed to an empty [] array, you could instead use:
<%= #ethos.try :tagline %>
Also note that in your original view <%= unless #work.nil? do %> should have been using a - and not a =.
Oh, and I encourage you to use HAML over ERB. With HAML, the view looks like this (easier to read, isn't it) :
= work_link %>
= #ethos. try :tagline
Your original view would look like this in HAML (remember, avoid conditionals in views as much as possible!)
- unless #ethos.blank?
- unless #work.nil? do
= link_to "Add Work", work_path
= #ethos.tagline
If the code works, what is your concern? Is it aesthetics or are you having difficulty reasoning about what the code is doing because there is so much nesting?.
The simplest solution is probably just to move the conditionals inline.
<%= link_to("Add Work", work_path) if #ethos.present? && #work %>
<%= #ethos.tagline if #ethos.present? %>
This will improve readability (and therefore maintainability), though it may not go far enough to keep the Rails purists happy. Zabba's answer presents several great choices that go further down the rabbit hole.

Rails Check if User Id is in Array

I'm trying to build a condition based on wether or not a "user" is a "member". Basically I need a way of checking if the current_user.id matches any of the user_id of any members. The non-working code I have right now is:
<% if current_user = #page.members %>
you can view this content.
<% end %>
I'm looking for something along the lines of: "If current_user.id exists in the "user_id" of any members."
Something like this, based on the field names in your question:
<% if #page.members.map(&:user_id).include? current_user.id %>
You can view this content
<% end %>
Assuming your #page.members variable contains an array, you can use the include? method:
<% if #page.members.include? current_user %>
you can view this content.
<% end %>
If you're using an array of ids, you will of course need to change the test slightly to look for the current user's id:
<% if #page.members.include? current_user.id %>
you can view this content.
<% end %>
#member_ids = #page.members.map{|m| m.id()}
then check for the condition as below
#memeber_ids.include? current_user.id()
Has said before include? should do the thing.
I'm just answering to tell you about a gem called CanCan, that gives you easy access for authorization "helpers".
Why you should use CanCan instead of doing what you are actually doing?
Don't reinventing the weel most of the times it's a goob practice.
You are placing business logic on the view (bad practice).
CanCan most likely has been developed thinking on security, and all the best practices in mind.
You save some developing hours.
Sorry if I repeated myself.

Resources