Is it possible to add a variable to an object in rails? - ruby-on-rails

I'm really frustrated with rails because of a ton of little problems like this.
I have a model called timelines. In it is a datetime column but the javascript that I'm passing the data too is expecting a date only. So I want to add a new string to my model object before passing it to the view. This seems impossible.
First I gather the data from the database and put it into an instance variable:
#timeline = Timeline.where(token: params[:token]).first
Then I try to add on to that variable like this:
#timeline.birthday = "1/1/2000"
I get an error that says:
undefined method birthday= for #<Timeline:0x00000105add0d0>
I'm guessing it's saying this because birthday is not a column in my database. I know it's not, and I don't care that it's not in my database. I just want to add onto my variable. Is this possible?

You need to add accessor methods to be able to get/set birthday. It won't be persisted, though.
class Timeline
attr_accessor :birthday
end
Alternative solution
The underlying problem you seem to be having ("javascript expects something else") can be solved in a couple of ways. Presenter pattern, for example. Or use ActiveModel Serializers.
This will allow you to keep the model as is, and, upon rendering, transform data to format expected by client-side.

You could convert the original datetime column to date by using:
your_column_name.strftime("%d/%m/%y")

Related

Retrieving Associated Records Dynamically (Tableize)?

I am trying to build a generalized function that can retrieve associations of given object. The object is passed, but what associations are to be retrieved needs to be dynamic.
Using a method called associations, I can get an array of models that associate with the given object. My problem is how to take that information and use it to retrieve the rails association (using the standard a = b.models).
I am trying to use tableize but it doesn't work (getting an undefined method error)--it doesn't seem to think of it as a table name.
My code essentially boils down to:
assoc = obj.associations
tablename = assoc[0].tableize
obj.tablename.each
What is the correct way to do this?
Try using the send method:
obj.send(tablename).each

Hash getter and setter on ActiveRecord object

I have an ActiveRecord object that was serializing a hash property to one of my database columns. I'd like to get away from this since querying by one of the hash keys is very difficult/not clean. So I've split all the keys of the hash up into separate properties on the model. However, I have a lot of places using this code so in the meantime while I convert everything I'd like to have a property on my ActiveRecord object that is for Rails only (i.e. it doesn't populate back to my database) that wraps up those properties into a hash like it used to be and allows values to be set and get.
So for instance, this is what I used to have:
class MyCls < ActiveRecord::Base
serialize :state, Hash
attr_accessible :id, :mode
I'm getting rid of :state and replace it with 7 different values that made up this hash. But I'd still like to be able to access those values like this: MyObj.state[:obj_num]. Even though I now have obj_num as a property (i.e. MyObj.obj_num). I'm thinking the best way to do this would be to have a state property with a getter and a setter, but I can't quite seem to get the syntax right. For the setter I'd need to support both setting the hash as a whole and setting individual keys.
First to say: I dont think thats the best solution. When you touch this code again in lets say 3 years it will be like "WHAAAAAT HAVE I DONE?"... It whould the best solution to replace all the snippets in your code with other code.
You can prepend the method_missing method of the object after removing this line serialize :state to fetch all calls that want to access the not anymore existing serialized field of the object. Its explained here:
http://blog.enriquez.me/2010/2/21/dont-forget-about-respond-to-when-implementing-method-missing/
Its called metaprogramming. Thats the "rails magic" that makes all the find_by_attribute_name stuff working without defining each of these methods. Can be cool stuff but you need to be very carefull and you need to know what your doing.

rails while loading data from database perform datatype conversion example datetime to time

Is it possible to perform type conversion in rails when we load data from database. I am trying to fetch some fields which are currently as datetime in database, I want them as date or time depending on the need in the application. I do not want to do the conversion in Controller or View as after some time the fields will get fixed in the database. If this can be handled in the Model?
As far as I understand you have one datetime attribute and you want to display it alternatively as date and as time depending on the situation
You could implement two methods in your model for example if you have Post model it would look like this
class Post
attr_accessible :updated_at
def updated_at_date
updated_at.to_date # or whatever formatting you want to apply to it
end
def updated_at_time
updated_at.to_time # or whatever formatting you want to apply to it
end
end
And in your controllers and views you will call updated_at_date or updated_at_time depending on the situation.
Later, when you change the data storage logic, you won't need to change any code in your app except the code inside the two methods inside your model

Type method interfering with database type column problem

I'm using Ruby on Rails and the paths_of_glory gem
I need to access the types of achievements that a user accomplishes in order to display a picture along with each particular achievement. When I try to access it via #user.achievements.type, I get an error that says that it wants to return "array" (as in achievements is an array) instead of actually returning the elements in the type column of my database.
Since every ruby object has a method called type, my call to access the type column of the database fails. When I try to change the entry in the table, the paths_of_glory gem says it needs a type column in order to function properly.
I'm not quite sure where to go from here in order to access that column in the database. Any suggestions?
Not entirely sure what you're asking here, but maybe this will help.
For the first thing, #user.achievements is an array because you have multiple achievements, and the type method is for individual elements of #user.achievements which is why that won't work just like that. You'll have to do something like this:
#user.achievements.each do |achievement|
# Do stuff here
end
Regarding the type column, type is a reserved column in Rails used specifically for Single Table Inheritance, where multiple Rails models use a single database table. So you can't access it directly. I assume that paths_of_glory uses STI in some manner. You can access the model's class with something like achievement.class, then if you want just the name of it you can try achievement.class.to_s.
#user.achievements.each do |achievement|
model = achievement.class # => MyAwesomeAchievementClass
#image = model.picture # You could write some method in the model like this
end

How do I handle data which must be persisted in a database, but isn't a proper model, in Ruby on Rails?

Imagine a web application written in Ruby on Rails. Part of the state of that application is represented in a piece of data which doesn't fit the description of a model. This state descriptor needs to be persisted in the same database as the models.
Where it differs from a model is that there needs to be only one instance of its class and it doesn't have relationships with other classes.
Has anyone come across anything like this?
From your description I think the rails-settings plugin should do what you need.
From the Readme:
"Settings is a plugin that makes managing a table of global key, value pairs easy. Think of it like a global Hash stored in you database, that uses simple ActiveRecord like methods for manipulation. Keep track of any global setting that you dont want to hard code into your rails app. You can store any kind of object. Strings, numbers, arrays, or any object."
http://github.com/Squeegy/rails-settings/tree/master
If it's data, and it's in the database, it's part of the model.
This isn't really a RoR problem; it's a general OO design problem.
If it were me, I'd probably find a way to conceptualize the data as a model and then just make it a singleton with a factory method and a private constructor.
Alternatively, you could think of this as a form of logging. In that case, you'd just have a Logger class (also a singleton) that reads/writes the database directly and is invoked at the beginning and end of each request.
In Rails, if data is in the database it's in a model. In this case the model may be called "Configuration", but it is still mapped to an ActiveRecord class in your Rails system.
If this data is truly static, you may not need the database at all.
You could use (as an example) a variable in your application controller:
class ApplicationController < ActionController::Base
helper :all
#data = "YOUR DATA HERE"
end
There are a number of approaches that can be used to instantiate data for use in a Rails application.
I'm not sure I understand why you say it can't fit in a Rails model.
If it's just a complex data structure, just save a bunch of Ruby code in a text field in the database :-)
If for example you have a complex nested hash you want to save, assign the following to your 'data' text field:
ComplexThing.data = complex_hash.inspect
When you want to read it back, simply
complex_hash = eval ComplexThing.data
Let me point out 2 more things about this solution:
If your data structure is not standard Ruby classes, a simple inspect may not do it. If you see #<MyClass:0x4066e3c> anywhere, something's not being serialized properly.
This is a naive implementation. You may want to check out real marshalling solutions if you risk having unicode data or if you really are saving a lot of custom-made classes.

Resources