middleman blockquote ruby function - ruby-on-rails

I am trying to create a method in ruby to handle block quotes from my slim blog posts. Right now, I have the following view helper:
def blockquote(content,author,source=nil,source_link=nil)
data = '
<blockquote>
<p>'+content.html_safe+'</p>
<footer>
<strong>'+author+'</strong>'
if source && source_link
data = data + '
<cite>
'+source+'
</cite>
'
end
data = data + '</footer></blockquote>'
return data
end
Which works for posts like..
= blockquote("When you grow up you tend to get told that the world is the way it is and you're life is just to live your life inside the world. Try not to bash into the walls too much. Try to have a nice family life, have fun, save a little money. That's a very limited life. Life can be much broader once you discover one simple fact: Everything around you that you call life was made up by people that were no smarter than you. And you can change it, you can influence it… Once you learn that, you'll never be the same again.","Steve Jobs, Apple Computers")
however, would there be a better way? I want to wrap the text in something like
- blockquote
When you grow up you tend to get told that the world is the way it is and you're life is just to live your life inside the world. Try not to bash into the walls too much. Try to have a nice family life, have fun, save a little money. That's a very limited life. Life can be much broader once you discover one simple fact: Everything around you that you call life was made up by people that were no smarter than you. And you can change it, you can influence it… Once you learn that, you'll never be the same again.
but I need a way to pass in the author, and option source + source link.
The current method also requires the quote to be on a single line, instead of multiple lines. Thoughts?

I would create a quote_template partial instead of coding html into a method like you did. Then just do something like this:
def blockquote(options={})
... #checks and business logic
render partial: 'quote_template', options
end
And you can initialize it like:
blockquote({
author: "Steve Jobs",
quote: "Some awesome quote...",
...
})
_quote_template.html.erb partial might look something like this:
<blockquote>
<p><%= options[:quote] %></p>
<footer>
<strong><%= options[:author] %></strong>
<% if options[:source] %>
<cite>
<%= options[:source] %>
</cite>
<% end %>
</footer>
</blockquote>

I created the following slim template in my partials directory:
blockquote
p
= locals[:quote]
footer>
strong
= locals[:author]
- if locals[:source]
cite
a[href="#{locals[:source_link]}"]
= locals[:source]
which can be called via middleman partials like:
= partial "components/blockquote", locals: {\
author: "Steve Jobs, Apple Computers",\
quote: "When you grow up you tend to get told that the world is the way it is and you're life is just to live your life inside the world. Try not to bash into the walls too much. Try to have a nice family life, have fun, save a little money. That's a very limited life. Life can be much broader once you discover one simple fact: Everything around you that you call life was made up by people that were no smarter than you. And you can change it, you can influence it… Once you learn that, you'll never be the same again."}

Related

Ruby on Rails: How to define a controller definition per shim?

First time asking something here on StackOverflow. So excited!
Basically, I'm wondering what the correct design pattern is for what I'm trying to accomplish. I have all my code working but was wondering it there's a more elegant, "RoR Way" to put it all together. For a language/framework so beautiful, it just feels like I've done this wrong:
I have a single master layout page ("WeekSummary") I'm using to display a bunch of "DaySummary" shims. All shims derive from the same template "_day_summary.html.erb."
On WeekSummary, I'm able to pass variables to individual shims fairly easily, eg:
<%= render 'layouts/day_summary', date: '2016-08-12' %>
<%= render 'layouts/day_summary', date: '2016-08-11' %>
But now I'm having trouble invoking a "day_summary" controller definition per each shim. Essentially, at this point in the render lifecycle, I believe I've already passed through the "C" part when the RoR engine called my "week_summary" definition (in which I did hold some business logic). But now I want the RoR engine to go back to the controller and call a "day_summary" controller definition per each shim I've defined on WeekSummary view page. I would like all variables/definitions to be then locally scoped to each shim (so I can reuse the same var names, etc).
I wasn't able to figure out how to do that though so right now I've simply dumped all my shim-specific business logic at the top of the "_day_summary.html.erb" in a massive <% %> block. Having so much business logic there in a View shim seems wrong though.
I hope this made sense. Does anyone have any suggestions for how to properly do this? Essentially, I'm trying to encapsulate the rendering of each shim into its own MVC lifecycle/pattern, if that makes sense. Thank you!
Edit: In response to kcdragon's code request on what's happening inside each shim:
So, for example, for each day_summary shim, I wish to calculate that day's pnl.
At the top level, in the week_summary controller def, I get all transactions:
#transactions = Transaction.all.order('ticker', 'date DESC')
Then in each shim, I filter #transactions by only the date I care about for that shim. Thus, a sample of each shim's business logic includes the below-- in this example, calculating that day's PnL:
transactions = #transactions.where(date: '2016-08-08')
pnlHash = Hash.new
totalPnl = 0
transactions.each do |t|
if !pnlHash.key?(t.ticker)
pnlHash[t.ticker] = t.pnl
else
pnlHash[t.ticker] += t.pnl
end
totalPnl += t.pnl
end
<%= totalPnl %> is then rendered elsewhere on the shim.
There's other business logic too that happens in the shim, but this is a good representative sample.
Now, obviously at the top level (week_summary), I could "pre-process" all daily PnL calculations and then store them in some massive hashtable which I'd then use to extract values per day_summary shim. (In this example, I guess that'd be a true model of the week_summary view.) But I don't want to do that. I want to encapsulate day_summary into its own thing, where all its business logic and rendering is processed on the fly as week_summary renders. Hopefully that makes sense?
Edit2: For sake of clarity, here's what each day_summary shim looks like. On the week_summary view, five of these guys are rendered, each one corresponding to its respective date:
Here's what the day_summary shim looks like.

Is there a way to do an early exit or "return" from a view in Rails?

Does Rails offer any way to exit early or "return" from a view that is being rendered?
For example, I have a view structured as follows:
<h1>Your records summary</h1>
<% if #current_user.has_records? %>
<p>You don't have any records.</p>
<% else %>
... long block of view emission code here ...
<% end %>
In non-erb code, I'd just return from that if condition, and wouldn't need to put that long block inside an else. It would look like:
<h1>Your records summary</h1>
<% if #current_user.has_records? %>
<p>You don't have any records.</p>
<% return (or something) %>
<% end %>
... long block of view emission code here ...
Is there a way to do something like that in the erb?
EDIT: To be clear, I'm not asking for alternate approaches, such as have been suggested. I'm not a Rails noob. I really just want to know whether Ruby provides a mechanism for what I suggested or not.
This is an old question, but I figured I'd take the time to spare future people the hour or so of their lives trying to figure out if this is doable.
I've discovered that, as far back as Rails 3.2, this is actually possible.
It requires some knowledge of ActionView internals and I do not advocate anyone do this in production code. Further, this particular implementation only works with the built-in ERB engine used by Rails which, itself, uses Erubi.
Alright, now that we're done with the warnings, on to the action!
The surprisingly simple answer is to return #output_buffer.to_s.
As long as you've closed all your HTML tags before returning, it seems to work and everything is correctly rendered.
For the curious, this output buffer is currently configured in the initializer for the Erubi ERB handler. With the rest of the work done by the underlying Erubi::Engine implementation.
I've poked around at something that provides a less brittle way to go about returning early, but I've unsuccessful so far.
In Rails 3.2.2, return inside a template works just fine for me.
<% return unless allowed_tags %>
IIRC there's no built-in mechanism for exiting a template early. This is in line with how (I think) a view layer should behave, although erb isn't quite a template engine.
The old-timey solution was to wrap your template in a catch and throw something from within the template, like a symbol.
You could also embed the eval inside a lambda, allowing return to work.
Still ew, though.
The best way is to handle the conditional in your controller before rendering the template. There you can early return a different template (like the Add Record form) or the results template.
You can also offload that logic to Javascript in the view itself.

Rails View DRYness - Do you set variables in the view or just make clean methods?

I have a view in which I have the same link 3 times (actual view is large):
%h1= link_to "Title", model_path(#model, :class => "lightbox")
= link_to "Check it out", model_path(#model, :class => "lightbox")
%footer= link_to "Last time", model_path(#model, :class => "lightbox")
That model_path(#model, :class => "lightbox") call, though fairly clean, can be made even leaner wrapping it in this (maybe you had some more options, so doing this was worthwhile):
def popup_model_path(model)
model_path(model, :class => "lightbox")
end
My question is, I am having to recalculate that path 3 times in a view. What is the preferred way of a) DRYing this up and b) optimizing performance?
I think setting variables at the top of the view might be a good idea here:
- path = model_path(#model, :class => "lightbox")
-# ... rest of view
It's almost like mustache in the end then. What are your thoughts?
I think using variables in the view is a good idea here. Since these method calls are exactly the same.
The solution as proposed by Matt i prefer in some cases, but not in this case, because i find it confusing: the fact that it is cached in the method is not clear, and if i want to see two different models in one page i still get the first cached link for both models.
So in this case I would choose the somewhat more explicit approach and assign it to a variable in the view.
I really hate putting variables in the view. I would change your helper to
def popup_model_path(model)
#model_path ||= {}
#model_path[model] ||= model_path(model, :class => "lightbox")
end
to "memoize" it, and just keep the three function calls.
This seems like a possible case of premature optimization. Making a function like popup_model_path is a fantastically DRY idea. Especially if that bit of code, however terse it may be originally, is going to be used frequently across multiple views. However, worrying about the performance impact of calculating the path 3 times in one view is, in my opinion, needless. Unless we're talking about something that is going to be used dozens or hundreds of times per view, and you're expecting many many simultaneous users, and the app is running on a shared server or something I really don't see what you have currently having any perceptible impact on performance.
As a general rule, I do my best to avoid variables in my view code. They make it harder to read and with a few exceptions (such as variables directly related to loops that display stuff like lists) I feel they kinda go against the whole MVC concept as I understand it.
I think above all else you should strive for code that is easily readable, understandable, and maintainable; both for yourself and others not previously familiar with your project. popup_model_path as you have it now is simple enough to where anyone who knows Rails can follow what you're doing. I don't see any need to make it any more complicated than that since it's not terribly repetitive. I wish I could find this excellent blog post I remember reading a while ago that made the point that DRYing up your code is great, but it has its limits, and like all great things the law of diminishing returns eventually kicks in.

convert HASH into ARRAY

After saving some values into the database, I am
finding it difficult to print them out. Though I have been able to
pull the data out of the database, the output is like the following:
#vars={:object=>"46789620999001", :source_id=>1, :comment=>"["This is
my first commenttoday and tommorrow", "This is my first commenttoday
and tommorrow", "This is my first commenttoday and tommorrow", "This
is my first commenttoday and tommorrow", "This is my first comment",
"This is my first comment", "its nice!!!", "Many people do not take
this serious. In this life we have a big role to play in making
ourselves what we would be. It is only God that can help us to live
that life which we have planned, so we can only pray to Him who is the
all and all in our life to help
us."]", :title=>"", :content=>"<div>Life is beautiful. In this life,
whatever you see is what you will use to make out your way. People
around you can help you in many things and ways but can never live
your life for you. It is left for you to live your life, make and take
decisions that you think will help you in living out your dream life.
I believe everybody has a dream life he would like to live. Whatever
decisions one take today will go a long way in determining the kind of
life the one will live in future.<br />Take this as an advise.Bye </
div><div class="blogger-post-footer"><img width='1' height='1'
src='https://blogger.googleusercontent.com/tracker/
6876835757625487750-2447909010390406819?l=godwinagada.blogspot.com'
alt='' /></div>", :author=>"["Godwin",
"ken"]", :category=>"Reality", :post_id=>"", :date=>"2010-06-04", :FileName=>"first"}
>]
please can someone help out in referring to each of the data in this
output eg.
#output.each { |g|
puts g.FileName
puts g.post_id
}
etc
Don't you want:
#vars[:FileName]
#vars[:post_id]
You have a hash, which contains a set of keys with each key pointing to a value. There are several ways you can deal with them:
If you want to just view it to debug it. Load pretty print (require 'pp') and pretty print it (pp #vars). An even better choice is the Awesome Print gem.
If you output the value of each pair, just iterate with each passing a block for your action:
#vars.each do |key, value|
puts "#{key} => #{value}
end
Try pp, from the standard library.
require 'pp'
pp #vars
There is another alternative called awesome_print, you can dl the gem from http://rubygems.org/gems/awesome_print that would look like this
require 'rubygems'
require 'ap'
ap #vars
Either of these should print the hash in a format that is easier to read.

use reserved rails word in scaffolding

I'm new to rails, but not to programming. I'm trying to create a Case Management app, I'm running the command
ruby script/generate scaffold Case casename:string caseid:string
This works fine, however because Case is a reserved word I'm getting errors when trying to view localhost:3000/Cases
Is there anyway around this or do I just have to use a different name?
Thanks in advance.
Is there anyway around this or do I just have to use a different name?
There are some words that you can't work around (see below). There may be a way to work around 'case' but you'll make life easier on yourself by changing the name. Don't sweat the small things - there're are plenty of real problems to worry about :-)
Other reserved words here and here
Good luck!
Think you are going to cause yourself more grief than it's worth, personally I would avoid reserved words if at all possible.
The errors are specific to using the word case, so if you still want to, you can make things work if you alter the default views from:
<% #cases.each do |case| %>
<tr>
<td><%=h case.casename %></td>
…
to:
<% #cases.each do |c| %>
<tr>
<td><%=h c.casename %></td>
…
This is an old question I see, but I try to use alternate spellings of such words. In this example, "Kase" could be used on the backend for cases. Another example would be "Transaktion" for "transactions."
As for handling this on front end, the built-in i18n support (http://guides.rubyonrails.org/i18n.html) may make things easier. For example:
# /config/locales/en.yml
en:
helpers:
label:
kase:
name: "Case name"
Also, I believe there are tricks you can use in the routes file to modify the URLs used, but I haven't tested any of this before.

Resources