How Do I Call An Array Written in My Model - ruby-on-rails

Greeting all
I would like to create an array in my model and then reference it later from a view or a helper. How do I do this?
This is in my Events model. Users can select a lunch type(1,2,3) for the event. Instead of hard-coding sandwich names, which can change, in my view, I thought I would keep the names in one place (model) then reference the name based on the lunch type chosen.
SANDWICHES = { 1 => 'Turkey', 2 => 'Veggie', 3 => 'Roast Beef' }
How do I call this from another script in my app like a view or a helper?
Event.SANDWICHES[1] does not work
event_obj.SANDWICHES[1] does not work
thanks for any help.

What you have there is a constant and you need to access it with Event::SANDWICHES.

What you are describing here is not a Model (in the rails way), it's simply a constant.
If you don't want to create an actual Model with its own database table, you could pull this out into a helper.
Such as fillings_helper.rb
def fillings
%q{Turkey, Veggie, Roast Beef}
end
Then you can use it in your views for a select box by passing in fillings
http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-select
You would need to set up a text field in your Event model to accept a string for fillings.
This isn't necessarily the best way from a database normalisation perspective, but it will do what you're asking for.

Related

Rails-Passing an object to a DB method

I'm wondering whether the following is possible in Rails. I'm pretty new to Rails, but it just seems like the type of thing I would expect Rails to make possible...
I am wondering whether a DB method (for example, find) can take an object and know automatically to look for its ID value in the appropriate foreign key column without being given the name of that column.
My specific use case is that I would like to make a generic method that checks whether two models are correlated via a connection-table or not.
(In other words, different tables will be linking different models, and thus will use different column names. I want to be able to pass in something [presumably objects of the relevant classes] and Rails will know that the id of #sample_model of class SampleModel should be searched for in the column sample_model_id.)
So the method would be something like:
def connected? (connection_table, model1, model2)
connection_table.class.find_by(model1, model2)
end
…and the method could know automatically that it's looking for model1.id in the model1_id column and the model2.id in the model2_id column.
Is this (or something like it) possible? If not, is there any other way to accomplish my goal (the generic-connection-checker method)?
This method should work as expected:
def self.find_by(obj1, obj2)
fk_1, fk_2 =
[obj1, obj2].map { |o| self.reflect_on_association(o.class.to_s.split("::").last.underscore.to_sym).foreign_key }
self.where(fk_1 => obj1, fk_2 => obj2).last
end

What is the proper way to validate the type when using single table inheritance (STI)?

I am trying to use single table inheritance for some of my models. The base model is a Tournament, and I wish to extend this to create different types of tournaments. For instance, I might want to add a SingleEliminationTournament, or a DoubleEliminationTournament, both of which would inherit from Tournament. I have 2 questions, both of them somewhat related.
1) I would like the user to be able to create tournaments with a form, and to do this they would need to select one of the subclasses. Is there a way to get all of the subclasses and use them to populate a select box or something like that?
2) Since this information is going into a form, it would be nice to be able to validate the input into type. To do this, I would like to add a validation in the Tournament class that could check to make sure the Type was valid.
Obviously, I could hard code the values into the validation and the form, but I would not like to do that. Any help would be appreciated. Thanks!
TheModel.subclasses
would give you a list of types you need to include, but only if the models are loaded at runtime. They will always be loaded in production mode. You will have to load them manually in development mode.
You could create a directory with tournaments in them and load them with Dir.glob('app/tournaments/**/*_tournament.rb'). This gives you a nice listing all the tournament files you've specified. Because of convention, you can then infer the proper class name for each tournament.
Store this list of tournament names somewhere for reference in you validations and forms.
I'm not a Rails expert and I'm not sure if this can be considered clean, but for the validation part of your question, this worked for me:
Inside Tournament model:
def validate_type_implemented
klass = type.constantize rescue Object
raise "Given type not available." unless klass.class == Class and klass <= self.class
end

How do I create the Controller for a Single Table Inheritance in Rails?

I am setting up the Single Table Inheritance, using ContactEvent as the Model that ContactEmail, ContactLetter, and ContactCall will all inherit.
But I'm stumped on how to create the routing and the controller.
For example, let's say I want to create a new ContactEvent with type Email.
I would like a way to do the following:
new_contact_event_path(contact, email)
This would take the instance from Contact model and from Email model.
Inside, I would imagine the contact_event_controller would need to know...
#contact_event.type = (params[:email]) # get the type based on what was passed in?
#contact_event.event_id = (params[:email]) #get the id for the correct class, in this case Email.id
Just not sure how this works....
I had similar problem.
See here how I solved it.
I would have a controller (and maybe views) for each of your resource types. So add a controller for ContactEmail one for ContactLetter etc. Don't bother with one for the base class ContactEvent. Then your paths would read something like:
new_contact_email_path(#contact) or new_contact_letter_path(#contact)
The controller actions would then use the right model for that they represent, ie:
#contact_email = ContactEmail.new(params[...])
If you can keep your three types of resources separate rather than trying to pass the type in and building the right object in one controller you should find life much easier. The downside is you may need more links/forms/views in the front end, however depending on your application that may not be a bad thing from the user's perspective.

polymorphic activerecords in rails?

Hi so I have a list of 'areas' that are just areas of my site. I want to be able to insert them in to the database and say what type of area they are, this could be the name of the model that inherits from a base Area. This way I can write a generic controller which uses different views and different logic from the loaded model to decide how the page should act.
Trouble is I have no idea how to do this as I'm new to rails.. Any pointers? (or anyone saying "don't do it like that! do it like this!" would also be much appreciated)
Thanks
I have just found Single Table Inheritance. This appears like it will solve my problem
for more information read here:
http://juixe.com/techknow/index.php/2006/06/03/rails-single-table-inheritance/
You'll want to create a column named :type
Rails will automatically use the type column to determine the class of the child class.
Then you can do something like:
class Area < ActiveRecord::Base
end
class UserPage < Area
end
So then when you do
UserPage.create( :key => 'value')
It will create an entry in your areas table with the type field set to UserPage.

Rails: getting data from a table for each iteraction of a loop

I have a loop (for item in #dataset) and I want, in each iteration, to get different data from another table and make some operations that will be printed in the view. I cant't get this data from the dataset used in the loop.
How can I do this according to MVC? I can put the code into the loop, in the view, but I think it's horrible.
Must I use a helper for do this, and call the function from the view?
If you have one table, and want to get data from another table, usually this is in the situation of a has_many relation. For example, we have #people (Person model), and each person has_many addresses (Address model). In those cases the best thing to do is this
# Controller
#people = Person.find(:all, :include => :addresses)
...
# View
#people.each do |p|
p.addresses.each do |address|
...
If your data is not just normal database tables (maybe you get it from a web service or so on), then a good thing to do is to build all the data in the controller ahead-of-time, then pass that to the view. Something like this
# Controller
#people = Person.find(:all)
#people.each do |p|
# attach loaded data to the person object in controller
p.addresses = Address.load_from_somewhere_by_name(p.name)
...
This way the view code stays clean, like this:
# View
#people.each do |p|
p.addresses.each do |address|
...
It is quite hard to tell about best solution for your problem without details about data and relations between your models(tables). The common idea is next: keep your views stupid. Get all data needed to render view inside your controllers action. Make all changes and calculations inside same action. Then in view use this data.
btw, if you are talking about N+1 problem then read more about 'include' and 'joins' ActiveRecord parameters.
If I was you I would create a separate class that encapsulates the dataset and contains all the logic involved in processing the dataset entries. This class could be iterable (respond to each). Then I would pass an instance of this class to the view and use only its methods there.
Person(id, name, other fields...)
Event(id, title, ...)
Date(id, date, time, event_id, ...)
Disponibility(id, percent, date_id, person_id, ...)
Of course, all the relationships are defined in the Model.
I have a view that shows all the dates for a event, it's easy. But I want, for each date, to print the data for all the people whose are available for that date. In my view, forgetting MVC design pattern, I could code something like this:
<% for date in #Dates
available = Disponibility.find_by_date_id(date.id)
for item in available
guy = Person.find_by_id(item.person_id)
%>
Render date and people available...
I want to avoid this in the view. I think the Orion Edwards' answer is the nearest for what I need, but, in that example, address is an empty field for Person table? Or how can I append a new attribute to Person class?
Although, am I missing any SQL trick for do this?
Keep all the logic on your #dataset item inside the controller action
Utilize methods in your models for the interaction with other model objects you need
You should be left with only #dataset for your view that you can render in a partial.
You would need to further explain your situation for any more of answer on that. What kind of operations and other models do you need to interact with? If you post your model associations I'm sure we could really square you away.
Good luck!

Resources