I have a form that I want a date in. The date that the controller defines is #date_end. I want this date in the form, but without an AR model this seems REALLY STUPIDLY hard. I used to use this:
= date_select :date_end_, nil, :default => #date_end
But this only works if your 'name' is different from the instance var. If they are the same you get an 'interning string' error.
The only way I've found to solve this is to add a method to Object to return self
class Object
def get_self
self
end
end
Then I can do:
= date_select :date_end, :get_self
But we all know this is stupid. But there doesn't seem to be another way...
Any suggestions?
Would something like this do the trick:
= select_date Date.today, :prefix => :date_end
According to this documentation, under section "4.1 Barebones Helpers", using this particular helper will create a series of select tags for the day, month year. The names should end up looking like "date_end[day]", "date_end[month]"...etc. Let me know if that helps.
Related
Simple question
In rails I have an ApplicationHelper method
def sum_customer_yearly_revenue(customer_id, year)
sum_customer_yearly_revenue = Sale.sum(:net_amount, :conditions => ['customer_id = ? AND financial_year = ?', customer_id, year])
end
In my view I then call sum_customer_yearly_revenue(123456, 2014). How do I call the same method but with 'all' years. If I was using SQL it would be sum_customer_yearly_revenue(123456, *) but that returns an error. If it pass in "" it looks for a year that is empty. If I leave it blank it just errors aswell.
def sum_customer_yearly_revenue(customer_id, year="all")
sales = Sale.where(customer_id: customer_id)
sales = sales.where(year: year) if year!="all"
sales.sum(:net_amount)
end
This might be useful to you. In this case if you want to retrieve sum for all year there is no necessary to pass second argument.
Change the method to:
def sum_customer_yearly_revenue(customer_id, year = nil)
conditions = { :customer_id => customer_id }
conditions.merge!(:financial_year => year) if year
Sale.sum(:net_amount, :conditions => conditions)
end
And call it like this:
sum_customer_yearly_revenue(123456)
Can't in this form. Make a new helper, sum_customer_total_revenue. Or introduce way more logic in this function, but that's not as pretty.
Also, not sure those should be any kind of helpers; that kind of stuff belongs right into a model. If you need it, make sure the model passes those information to the view by including it from a controller, not directly in a helper.
(EDIT: upvoted jbmyid; that's a better syntax to do this. However... Still think it doesn't belong in a function that's called the way it's called; still think it doesn't belong in a helper.)
I have a model called foo with a date field.
On my index view, I am showing a typical "weekly view" for a specified week. To put the data in my view, I loop through each day of the specified week and query the data one day at time. I do this so that I can make sure to put a NIL on the correct day.
foos_controller.rb
for day in 0..6
foo = Foo.this_date(#date+day.days).first
#foos[day] = foo
end
index.html.haml
- for day in 0..6
%li
- if #foos[day].nil?
Create a new foo?
- else
Display a foo information here
Obviously, there's a lot of things wrong here.
I should find someone smart member to tell me how to write a good query so that I only have to do it once.
I should not have any if/else in my view
My goal here is to either show the content if the it is there for a particular day or show a "create new" link if not.
thanks for the help in advance!!
First, I have no idea what this_date actually does, but I'll assume it's retrieving a record with a specific date from your datastore. Instead of doing 7 queries, you can condense this into one using a date range:
Foo.where(date: (#date..(#date + 6.days)))
You can tack on a .group_by(&:date) to return something similar to the hash you are manually constructing, but using the actual dates as keys instead of the date offset.
To iterate over the dates in the view, I would recommend using Hash#fetch, which allows you to define a default return when a key is not present, e.g:
hash = { :a => 1, :b => 2 }
hash.fetch(:a){ Object.new } #=> 1
hash.fetch(:c){ Object.new } # #<Object:...>
The question now is what object to substitute for nil. If you want to avoid using conditionals here, I'd recommend going with the NullObject pattern (you could involve presenters as well but that might be a bit overkill for your situation). The idea here is that you would create a new class to substitute for a missing foo, and then simply define a method called to_partial_path on it that will tell Rails how to render it:
class NullFoo
def to_partial_path
"null_foos/null_foo"
end
end
You'll need to create partials at both app/views/foos/_foo.html.erb and app/views/null_foos/_null_foo.html.erb that define what to render in each case. Then, in your view, you can simply iterate thusly:
<% (#date..(#date + 6.days)).each do |date| %>
<%= render #foos.fetch(date){ NullDate.new } %>
<% end %>
Is this appropriate for your situation? Maybe it's also a bit overkill, but in general, I think it's a good idea to get in the habit of avoid nil checks whenever possible. Another benefit of the NullObject is that you can hang all sorts of behavior on it that handle these situations all throughout your app.
I've been trying to come up with a way to declare array constants in a class, and then present the members of the arrays as grouped options in a select control. The reason I am using array constants is because I do not want the options being backed by a database model.
This can be done in the basic sense rather easily using the grouped_collection_select view helper. What is not so straightforward is making this localizable, while keeping the original array entries in the background. In other words, I want to display the options in whatever locale, but I want the form to submit the original array values.
Anyway, I've come up with a solution, but it seems overly complex. My question is: is there a better way? Is a complex solution required, or have I overlooked a much easier solution?
I'll explain my solution using a contrived example. Let's start with my model class:
class CharacterDefinition < ActiveRecord::Base
HOBBITS = %w[bilbo frodo sam merry pippin]
DWARVES = %w[gimli gloin oin thorin]
##TYPES = nil
def CharacterDefinition.TYPES
if ##TYPES.nil?
hobbits = TranslatableString.new('hobbits', 'character_definition')
dwarves = TranslatableString.new('dwarves', 'character_definition')
##TYPES = [
{ hobbits => HOBBITS.map {|c| TranslatableString.new(c, 'character_definition')} },
{ dwarves => DWARVES.map {|c| TranslatableString.new(c, 'character_definition')} }
]
end
##TYPES
end
end
The TranslatableString class does the translation:
class TranslatableString
def initialize(string, scope = nil)
#string = string;
#scope = scope
end
def to_s
#string
end
def translate
I18n.t #string, :scope => #scope, :default => #string
end
end
And the view erb statement look like:
<%= f.grouped_collection_select :character_type, CharacterDefinition.TYPES, 'values[0]', 'keys[0].translate', :to_s, :translate %>
With the following yml:
en:
character_definition:
hobbits: Hobbits of the Shire
bilbo: Bilbo Baggins
frodo: Frodo Baggins
sam: Samwise Gamgee
merry: Meriadoc Brandybuck
pippin: Peregrin Took
dwarves: Durin's Folk
gimli: Gimli, son of Glóin
gloin: Glóin, son of Gróin
oin: Óin, son of Gróin
thorin: Thorin Oakenshield, son of Thráin
The result is:
So, have I come up with a reasonable solution? Or have I gone way off the rails?
Thanks!
From the resounding silence my question received in response, I am guessing that there is not a better way. Anyway, the approach works and I am sticking to it until I discover something better.
In my view page, i am using form_tag to create a form which will pass a string of ids from a hidden field to the controller code.
In my controller code, i am looping through an array of ids to update each record containing that id in the Expression table. But the code below does not seem to work.
I would really appreciate it if somebody could give me some suggestion regarding what is wrong with the code below.
def update_expression
#emi_ids_array = params[:emi_ids].split(/,/)
#sub_id = params[:sub_id]
#emi_ids_array.each do |emi_id|
#existing_exp = Expression.find(:first, :conditions => [ "EXT_EMI_ID = ? and EXT_SUB_FK = ?", emi_id, #sub_id])
#expression = #existing_exp.update_attributes(
:EXT_SUB_FK => #sub_id,
:EXT_PRESENCE => "present",
:EXT_STRENGTH => "weak",
:EXT_EMI_ID => emi_id
)
end
end
Try converting the array of ID's (and the sub_id) to integers.
Is it the finding of the object that fails, or the update? Output the #expression.errors after the update call to see if there are any validations failing.
Is there a reason for all the instance variables? You don't need the #'s if the variable doesn't go beyond that method. Also the #expression item seems superfluous, you're just duplicating the #existing_exp object, you don't need to put the return into a new object, especially if it's replaced each time the loop runs anyway.
Found a temporary solution. 'update_attributes' does not seem to work, so i opted for 'update_all' attribute
Expression.update_all({:EXT_PRESENCE => "present", :EXT_STRENGTH => "weak"},['EXT_EMI_ID = ? and EXT_SUB_FK = ?', emi_id, #sub_id])
Hopefully, it might be useful to someone else
In my Article model (rails 3), I want to create methods that takes a parameter.
So I can do things like:
Article.get_by_id(:cache => true, :cache_expire => some_date)
I want to re-use this parameter, how can I do this?
The parameter is a hash of options, and I want to use it in many of my controllers methods.
you can add following method to Article model
self.get_by_id(options = {})
cache = options['cache']
end
Now the parameter sent to the above method can be accessed using option hash. i.e, options['cache'] and options['cache_expired'].
Do you mean like this?
custom_options = { :cache => true, :cache_expire => some_date }
Article.get_by_id(custom_options)
I'm sorry if I am not getting you but your question was very brief.