Here is the thing. I have a Country model with two columns "languages" and "default_language". So for instance, for switzerland these columns are set respectively to "de,fr,it" and "de".
Now, if I do Country.languages I get the "de,fr,it" string. How can I override this so when I get Country.languages I get an array ["de","fr","it"] ?
Sure I could create a function def available_languages, but still, I don't want languages to be public.
For simple arrays in this case, it is probably better to write your own solution.
This can be done by overriding the getter/setter methods:
In your model:
class Country < ActiveRecord::Base
def languages
read_attribute(:languages).split(',')
end
def languages=(array)
write_attribute(:languages,array.join(','))
end
end
For hashes, you can use ActiveRecord::Store, see http://api.rubyonrails.org/classes/ActiveRecord/Store.html
For more general objects (not just arrays, you can use serialize), see http://duanesbrain.blogspot.co.nz/2007/04/ruby-on-rails-persist-array-to-database.html
Related
Suppose I have a class in, say, Python e.g.:
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
And then I start adding a lot of convenience methods e.g.:
class Date:
# ...
def num_days_in_month(self):
pass
def first_day_of_month(self):
pass
def last_day_of_month(self):
pass
# ...
def next_new_moon(self):
pass
What is the verb for the thing I am doing, and what is the noun for the stuff I am adding to the class, and what is an adjective for a class with a lot of it. I can only think of bad/overly verbose ways of describing this:
The stuff I am adding is "syntactic sugar" and I am "sugaring" or "sweetening" the class, and it makes the class "sweet"/"sugared"
The stuff I am adding is "tooling" and I am "tooling" the class, and it makes that class "tooled'
The things I am adding are "methods" and I am "methoding" the class, and it makes the class ???
The things I am adding are "convenience methods" and I am "conveniencing" the class, and it makes the class "convenienced"
What's the best way?
I don't want just a general world like "developing." I also don't just want a noun, I also want a corresponding single concise verb to describe the act of adding these things (so not "adding convenience methods"). I want to be able to use these in sentences like:
"When designing a class, one important decision to make is how much ____________ to add. On the one hand, you can waste a lot of time __________ing your class and end up with big piles of code that will never get called. On the other, a class that is not ________ enough will require more code to be written by its users.
I saw in the documentation that in ROR 3.2 it's generally better to use scope methods in the model for retrieving records with arguments instead of lamda scopes
Using a class method is the preferred way to accept arguments for
scopes. These methods will still be accessible on the association
objects
But when do you use dynamic finders (such as find_by_* instead of scope and scope methods? dynamic finders can also receive arguments and they seem to be simpler to use directly from the view.
If I want to retrieve all the records that have
attribute1 == [boolean] AND attribute2 IN [array]
which method is advisable (scope, scope method, or dynamic finder?)
You shouldn't be using any finders in your views.
I would probably write this using a class method.
something like this:
class Dog < ActiveRecord::Base
attr_accessible :chewed, :color
def self.toys chewed = false, colors = []
where chewed: chewed, color: colors
end
end
My app has points / awards that can be achieved after a number of actions take place, which generally trigger when a record has been added (completing a mission, etc.)
I wrote a fairly involved function that audits all of the data, and awards the proper amount of points, user ranking, etc. This needs to be called after each one of these records is saved.
I know I can use Observers to call the function after a number of model saves, but I am unclear on where exactly the put said function, and how to call it.
Much appreciated in advance!
Observers usually go in app/models/. You can automatically generate an observer class for a model with the command rails generate observer YourModel. This will generate the file `app/models/your_model_observer.rb'.
By the way, aftersave is not a very descriptive method name. If it does a lot of things it's better to break it up into several methods each of which do one thing, and give each a descriptive name, e.g.:
class YourModelObserver < ActiveRecord::Observer
def after_save your_model_instance
calculate_points your_model_instance
assign_awards your_model_instance
end
private
def calculate_points inst
# ...
end
def assign_awards inst
# ...
end
end
I have a Technique model which belongs_to User and is indexed by Thinking Sphinx.
I also have a method in my model that returns an array of Technique objects:
def possible_children(user)
user.techniques - (self.children + [self])
end
This just takes the techniques that a user has, subtracts out those of the techniques that are already the children of the 'self' technique object, along with 'self' itself, and returns the remaining technique objects.
Then in a controller I instantiate a collection of possible children like so:
#possible_children = #technique.possible_children(current_user).search params[:search]
This returns an "undefined method 'search' for #"
Not sure if this is relevant but the controller this takes place in is not the TechniquesController.
What I am trying to do is search an arbitrary collection returned by a Model method.
Any ideas?
Let me know if I need to provide more information. Thank you.
I'm afraid this isn't possible with Thinking Sphinx - at least, not that simply. What you could do is use the objects you want to search across, grab their ids, and use that in a filter:
possible_children = #technique.possible_children(current_user)
Technique.search params[:search],
:with => {:sphinx_internal_id => possible_children.collect(&:id)}
Sphinx has its own id, but the primary key from the database is stored as the attribute sphinx_internal_id by Thinking Sphinx.
I have two models than inherited from the same abstract base class.
I would expect to be able to get all instances from classes that are children of the base class with something like AbstractClass.objects.all()
Of course I could join queries on all children but that's awful and it stops working if I add new children class.
Is this possible with Django ORM ? What would be the elegant solution ?
I have used django's other inheritance methods because I hit the same problem you are running into. I'm not sure if there is an elegant solution. Ultimately, you need several queries done on the DB and for the results to be merged together. I can't picture the ORM supporting that.
Here is my usual hackish approach for this situation:
class NotQuiteAbstractBaseClass(models.Model):
def get_specific_subclass(self):
if self.model1:
return self.model1
elif self.model2:
return self.model2
else:
raise RuntimeError("Unknown subclass")
class Model1(NotQuiteAbstractBaseClass):
def whoami(self):
return "I am a model1"
class Model2(NotQuiteAbstractBaseClass):
def whoami(self):
return "I am a model2"
Then, you can query the entire list like this:
for obj in NotQuiteAbstractBaseClass.objects.iterator():
obj = obj.get_specific_subclass()
print obj.whoami()