I wish to use this code but I am having difficulty getting it working. It is contained in a model:
def to_pdf
title = #account.name
subtitle = "Account Statement: #{#month_name} #{#year}"
StatementPDF.new(title, subtitle, transactions).render
end
The transactions method is stored in a helper file (dont ask) but I cant seem to call it. Any suggestions.
def transactions(account_id, start, finish)
return #transactions if #transactions
response = get_call('/Accounts/Statements/' + account_id.to_s + '/' + start + '/' + finish)
response = JSON.parse(response.body)
#transactions = response.map {|txn| Transaction.new(txn)}
end
I have had suggestions regarding placement of my transactions method but have to have it there for reasons above my paygrade. The strangest thing about this is that it worked at a point and when i reloaded the environment just to check everything was working as should be it stopped working again. Any suggestions?
(Moved to answer for readability, but it's more an extended comment.)
Helpers are for the view.
Making HTTP requests from the view layer is bad because (a) it puts too much logic into the view layer, and (b) it's counter-intuitive and could be misused, e.g., someone could accidentally (or purposefully) call it multiple times, potentially incurring the cost twice.
(Partially alleviated because of the sort-of caching, depending on access to #transactions.)
Something like this belongs in a utility class, called from the controller. (In general only the controller should generate data passed into the view.) That makes the controller easier to test because you can trivially mock/stub a top-level utility class method instead of having to use a fake web layer, mocking get_call, etc.
Unrelated, but Ruby favors string interpolation over concatenation, e.g.,
response = get_call("/Accounts/Statements/#{account_id.to_s}/#{start}/#{finish}")
I'm also not a fan of raw calls like this and prefer to see them behind some form of API mechanism, particularly if this is a pattern used throughout the app, something like:
def get_transactions_data(account_id, start, finish)
response = get_call("/Accounts/Statements/#{account_id.to_s}/#{start}/#{finish}")
JSON.parse(response.body)
end
(I might even create a URL builder as well, but I like really, really concise, communicative code.)
The step of transforming them into Transaction objects may or may not belong there as well, it depends on how your app is laid out, and how strongly your layers are separated.
Related
The Rails 'flash' message system is very useful, but I've always found the details of its implementation make its use awkward.
Specifically, the flash messages are cleared at the end of a response. This means that you have to work out whether they're going to be used in a direct page render or a redirect, then inform the flash system by using 'now' if it's not a redirect.
This seems overly complex and error-prone.
Occasionally I find myself building things that need to exhibit flash-like behaviour, and the process I use is slightly different:
class FlashlikeStore
attr_accessor :session
def initialize(session)
session[:flashlike] ||= []
self.session = session
end
def add(name, data)
self.store << { name: name, data: data }
end
def read
session.delete(:flashlike).to_json
end
def any?
store && store.any?
end
protected
def store
session[:flashlike]
end
end
With a little syntactic sugar in the application helper I can easily add my name-value pairs, and the act of reading it deletes the data. (In this case I'm actually reading this in via AJAJ, but that isn't important here.)
The upshot is that messages are only ever read once, with no need up-front to determine or guess when they're going to appear. They're read when they're needed, then they go away.
One could argue, I suppose, that a call to an object shouldn't both read data and change state, so the 'read' method could be split into a 'read' and a 'wipe' if you wanted to be purist that way. (Although you probably wouldn't be using Rails if you were.)
So the question is this: am I missing something? Is there a compelling reason for the way Rails flash messaging works, with its need for the 'now' method?
I was reading an article about Rails controllers, can you help me understand please what is meant by the following phrase:
"The best controller is Dilbert-esque: It gives orders without knowing (or caring) how it gets done."
Is it true, in your opinion?
If, for example, I am accessing the index page associated with the subjects controllers, I would define the index method in the subjects_controller.rb rigorously, so I am confused as to what they mean in the article, as I would have thought the opposite.
Any pointers, please?
Thank you and sorry if this is too interpretable. This is the original article: http://betterexplained.com/articles/intermediate-rails-understanding-models-views-and-controllers/
This article is talking about MVC architecture. What's important to take away from an article like this is the fact that Rails is best written with Fat Models and Thin Controllers. This means that you want to have the bulk of your methods/functions in your Model and want to have calls to the functions from your controller. Index is a bad example since typically you're not going to have a lot going on in there.
Your controller for index will typically look something like this
def index
#subjects = Subject.all
end
If you want to scope order for displaying your subjects though, you would do that in your model with a block as follows:
default_scope { order("id DESC") }
A less contrived example might look something like this: Say for example you have an app that accepts input, takes that input and tallies several counters based on what the user entered. Your controller might be named subject_tally and look like this:
def subject_tally
#subject = Subject.find(params[:id])
#subject.winnings += 1
#subject.total_matches += 1
#subject.win_percentage = #subject.winnings.to_f/#subject.total_matches
redirect_to subjects_path
end
THIS IS WRONG. This is a very fat controller and easily moved to the Model where it should be.
If written properly it would look something like this:
subjects_controller.rb: (The Controller)
def subject_tally
#subject = Subject.find(params[:id])
#subject.subject_tally
redirect_to subjects_path
end
subject.rb: (The Model)
def subject_tally
self.winnings += 1
self.total_matches += 1
self.win_percentage =winnings.to_f/total_matches
end
So as you can see, you make only one call from the controller and it "doesn't care" what is actually going on in the backend. It's literally there to pass a value (in this case, the ID of the subject in question) and direct you to another page, in this case, the index.
Furthermore, if you'll notice, you don't need to add that pesky #subject everywhere in your model's subject_tally function... you can reference the attributes of the object just by using self.winnings where you're assigning to an attribute. Ruby is smart enough to know the current subject the method applies to (since you called that function ON a subject from the controller) and in fact you don't even need the self. if you're just retrieving the attributes instead of assigning them... which is why we didn't need self before winnings.to_f or the last line's total_matches.
Very convenient, less code, less time, yay.
The best controller is Dilbert-esque: It gives orders without knowing
(or caring) how it gets done.
means that you should put less logic as you can in the controller,
the controller should only know what to call to get what it needs, and should not know how to carry out a certain action.
In the "Sandy Metz rules" for rails developers (http://robots.thoughtbot.com/sandi-metz-rules-for-developers), she says:
Controllers can instantiate only one object. Therefore, views can only
know about one instance variable and views should only send messages
to that object
only one object could seem a bit extreme, but makes the idea about how much business logic (no logic) you should put in the controller.
I'm trying to wrap my head around remote code execution vulnerabilities in ruby/rails when contantize is used.
I understand that being able to provide any class name to the server could be potentially dangerous, but I'm wondering if this by itself is dangerous.
for example, if a rails controller code looks something like this (i.e. executes a hardcoded method on the instantiated object):
klass = params[:class].classify.constantize
klass.do_something_with_id(params[:id]) if klass.respond_to?('do_something_with_id')
Is this code vulnerable? Or only in combination with being able to also specify the method to be called on the class?
Turning a string into a constant isn't dangerous in itself, but how that constant is used is potentially dangerous (i.e. the method that is then called).
If you really need to do this, then it's probably best to provide a list of classes that are allowed. E.g.
klass = params[:class].classify
if %w(Class1 Class2 Class3).include? klass
klass.constantize.do_something_with_id(params[:id])
else
raise 'Forbidden'
end
However it's done, it helps you to sleep at night to know that the input is considerably limited.
Update
Another way of controlling the creation, which is more explicit but also more verbose, is to use a case statement:
def create_klass(option)
case option
when "option1"
Class1
when "option2"
Class2
when "option3"
Class3
else
raise "Unknown option"
end
end
This way, you don't need to expose the internals of your system to the client. If there are many options, then you could use a hash with options mapping to classes.
I have been pulling my hair out for weeks on this niggling problem, and I just can't find any info or tips on how or what to do, so I'm hoping someone here on the RubyMotion forums can help me out.
Apologies in advance if this is a little long, but it requires some setup to properly explain the issues. As background, I've got an app that uses a JSON/REST back-end implemented ina Rails app. This is pretty straightforward stuff. The back-end is working fine, and up to a point, so is the front end. I can make calls to populate model objects in the RubyMotion client and everything is great.
The one issue is that all of the http/json libs use async calls when processing requests. This is fine, and I understand why they are doing it, but there are a couple of situations where I need to be able to wait on a call because I need to do something with the returned results before proceeding to the next step.
Consider the example where a user wants to make a payment, and they have some saved payment information. Prior to presenting the user with a list of payment options, I want to make sure that I have the latest list at the client. So I need to make a request to a method on the user object that will grab the current list (or timeout). But I don't want to continue until I am sure that the list is either current, or the call to the back-end has failed. Basically, I want this call to block (without blocking the UI) until the results are returned.
Alternatives such as polling for changes or pushing changes from the back-end to the front are not appropriate for this scenario. I also considered simply pulling the data from the destination form (rather than pushing it into the form) but that doesn't work in this particular scenario because I want to do different things depending on whether the user has zero, one or multiple payment options saved. So I need to know in advance of pushing to the next controller, and to know in advance, I need to make a synchronous call.
My first attack was to create a shared instance (let's call it the SyncHelper) that I can use to store the returned result of the request, along with the "finish" state. It can provide a wait method that just spins using CFRunLoopRunInMode either until the request is finished, or until the request times out.
SyncHelper looks a bit like this (I've edited it to take some irrelevant stuff out):
class SyncHelper
attr_accessor :finished, :result, :error
def initialize()
reset
end
def reset
#finished = false
#result = nil
#error = nil
end
def finished?
#finished
end
def finish
#finished = true
end
def finish_with_result(r)
#result = r
#finished = true
end
def error?
!#error.nil?
end
def wait
timeout = 0.0
while !self.finished? && timeout < API_TIMEOUT
CFRunLoopRunInMode(KCFRunLoopDefaultMode, API_TIMEOUT_TICK, false)
timeout = timeout + API_TIMEOUT_TICK
end
if timeout >= API_TIMEOUT && !self.finished?
#error = "error: timed out waiting for API: #{#error}" if !error?
end
end
end
Then I have a helper method like this, which would allow to me to make any call synchronous via the provision of the syncr instance to the invoked method.
def ApiHelper.make_sync(&block)
syncr = ApiHelper::SyncHelper.new
BubbleWrap::Reactor.schedule do
block.call syncr
end
syncr.wait
syncr.result
end
What I had hoped to do was use the async versions everywhere, but in the small number of cases where I needed to do something synchronously, I would simply wrap the call around a make_sync block like this:
# This happens async and I don't care
user.async_call(...)
result = ApiHelper.make_sync do |syncr|
# This one is async by default, but I need to wait for completion
user.other_async_call(...) do |result|
syncr.finish_with_result(result)
end
end
# Do something with result (after checking for errors, etc)
result.do_something(...)
Importantly, I want to be able to get the return value from the 'synchronised' call back into the invoking context, hence the 'result =...' bit. If I can't do that, then the whole thing isn't much use to me anyway. By passing in syncr, I can make a a call to its finish_with_result to tell anyone listening that the async task has completed, and store the result there for consumption by the invoker.
The problem with my make_sync and SyncHelper implementations as they stand (apart from the obvious fact that I'm probably doing something profoundly stupid) is that the code inside the BubbleWrap::Reactor.schedule do ... end block doesn't get called until after the call to syncr.wait has timed out (note: not finished, because the block never gets the chance to run, and hence can't store result in it). It is completely starving all other processes from access to the CPU, even tho the call to CFRunLoopRunInMode is happening inside wait. I was under the impression that CFRunLoopRunInMode in this config would spin wait, but allow other queued blocks to run, but it appears that I've got that wrong.
This strikes me as something that people would need to do from time-to-time, so I can't be the only person having trouble with this kind of problem.
Have I had too many crazy pills? Is there a standard iOS idiom for doing this that I'm just not understanding? Is there a better way to solve this kind of problem?
Any help would be much appreciated.
Thanks in advance,
M#
When you need to display the payment options, display a HUD, like MBProgressHUD to block the user from using the UI and then start your network call. When the network call returns, dismiss the HUD in either in your success/failure blocks or in the delegate methods and then refresh your view with the data received.
If you don't like the HUD idea you can display something appropriate in your UI, like a UILabel with "loading..." or an UIActivityIndicatorView.
If you need to get the data to display first thing, do it in viewDidAppear; if it happens on an action then move your transition to the next view (performSegueWithIdentifier or whatever) into your network success block/callback and make the network call when the action is called.
There should be examples in your networking library of how, or take a look at the usage sample code in MBProgressHUD itself https://github.com/jdg/MBProgressHUD.
Here's what I do to make multi-threaded synchronized asynchronous calls.
def make_sync2(&block)
#semaphore ||= Dispatch::Semaphore.new(0)
#semaphore2 ||= Dispatch::Semaphore.new(1)
BubbleWrap::Reactor.schedule do
result = block.call("Mateus")
#semaphore2.wait # Wait for access to #result
#result = result
#semaphore.signal
end
#semaphore.wait # Wait for async task to complete
result = #result
#semaphore2.signal
result
end
as borrrden just said, I'd use a dispatch_semaphore
def ApiHelper.make_sync(&block)
#semaphore = Dispatch::Semaphore.new(0)
BubbleWrap::Reactor.schedule do
# do your stuff
#result = block.call()
#semaphore.signal
end
#semaphore.wait
#result
end
this is how I'd handle it on Rubymotion
You can also use synced queues.
Dispatch::Queue.new('name').sync
Dispatch::Queue.main.sync
Take a look at more examples of usage: http://blog.arkency.com/2014/08/concurrent-patterns-in-rubymotion/
At about the 19:00 mark in his RailsConf presentation, David Heinemeier Hansson talks about the downsides of instance_eval:
For a long time I ranted and raved
against instance_eval, which is the
concept of not using a yielded
parameter (like do |people|) and
just straight do something and then
evaluate what's in that block within
the scope of where you came from (I
don't even know if that's a coherent
explanation)
For a long time I didn't like that
because it felt more complex in some
sense. If you wanted to put your own
code in there were you going to
trigger something that was already
there? Were you going to override
something? When you're yielding a
specific variable you can chain
everything off that and you can know
[you're] not messing with anybody
else's stuff
This sounded interesting, but a) I don't know how how instance_eval works in the first place and b) I don't understand why it can be bad / increase complexity.
Can someone explain?
The thing that instance_eval does is that it runs the block in the context of a different instance. In other words, it changes the meaning of self which means it changes the meaning of instance methods and instance variables.
This creates a cognitive disconnect: the context in which the block runs is not the context in which it appears on the screen.
Let me demonstrate that with a slight variation of #Matt Briggs's example. Let's say we're building an email instead of a form:
def mail
builder = MailBuilder.new
yield builder
# executed after the block
# do stuff with builder
end
mail do |f|
f.subject #subject
f.name name
end
In this case, #subject is an instance variable of your object and name is a method of your class. You can use nice object-oriented decomposition and store your subject in a variable.
def mail &block
builder = MailBuilder.new
builder.instance_eval &block
# do stuff with builder
end
mail do
subject #subject
name name # Huh?!?
end
In this case, #subject is an instance variable of the mail builder object! It might not even exist! (Or even worse, it might exist and contain some completely stupid value.) There is no way for you to get access to your object's instance variables. And how do you even call the name method of your object? Everytime you try to call it, you get the mail builder's method.
Basically, instance_eval makes it hard to use your own code inside the DSL code. So, it should really only be used in cases where there is very little chance that this might be needed.
Ok, so the idea here is instead of something like this
form_for #obj do |f|
f.text_field :field
end
you get something like this
form_for #obj do
text_field :field
end
the first way is pretty straight forward, you end up with a pattern that looks like this
def form_for
b = FormBuilder.new
yield b
b.fields.each |f|
# do stuff
end
end
you yield out a builder object that the consumer calls methods on, and afterwards you call methods on the builder object to actually build the form (or whatever)
the second one is a bit more magical
def form_for &block
b = FormBuilder.new
b.instance_eval &block
b.fields.each |f|
#do stuff
end
end
in this one, instead of yielding the builder to the block, we take the block and evaluate it in the context of the builder
The second one increases complexity because you are sort of playing games with scope, you need to understand that, and the consumer needs to understand that, and whoever wrote your builder needs to understand that. If everyone is on the same page, I don't know that it is nessicarily a bad thing, but i do question the benefits vs the costs, i mean, how hard is it to just tack on an f. in front of your methods?
The idea is that it's a little dangerous in that you can never be quite sure you're not going to break something without reading all the code that deals with the object your using instance_eval on.
Also if you , say, updated a library that didn't change the interface much but changed a lot of the object internals you could really do some damage.