I am new on rails ,actually I am creating a bakery application in which I need to add multiple cookies to one single oven. I am not getting right code for has_many association and how to apply a loop and condition in file having extension of .html.haml
What I understand is you have two classes
Oven
and
Cookie
Cookie Class:
class Customer < ActiveRecord::Base
belongs_to :oven
end
Oven Class:
class Customer < ActiveRecord::Base
has_many :cookies
end
Now you want to traverse on all the cookies which belongs to one oven in the view, you can do as following in the view file(html.erb):
<% #oven.cookies do |c| %>
<%= do something %>
<%end %>
where #oven is instance variable returned from controller.
Hope this might helps you Rails Association
Related
EDIT
I am new to rails and got stuck at this step.Researched whatever I could on the internet but could not fix this. Please help! I am using Rails 3.2.13.
This is how my models look now. Excuse me for the typo, if any, as this is a made up example. cleaned up a bit but again the same problem. Could be bug not sure.
I have 3 Models:
1.Cuisine (example Thai/Mexican/Italian)
class Cuisine < ActiveRecord::Base
has_many :testers, :through => :ratings
has_many :ratings, :inverse_of => :cuisine
2.Testers
class Tester < ActiveRecord::Base
has_many :cuisines, :through => :ratings
has_many :ratings, :inverse_of => :tester
3.Rating (note:had the inverse_of here too but did not work)
class Rating < ActiveRecord::Base
belongs_to :tester
belongs_to :cuisine
testers_controller
class TestersController < ApplicationController
def update ##TO DO: SAVE (tester + cuisine IDS) IN THE ratings/JOIN TABLE
#tester = Tester.find(params[:id])
#tester.ratings.create
render text: 'Success'
end
This is form in the view. I am not using / rendering any partials for this exercise.
<%= form_for :rating, url: ratings_path do |f| %>
<h3>Review:</h3>
<% for cuisine in Cuisine.find(:all) %>
<div>
<%= check_box_tag("tester[cuisine_ids][]", cuisine.id) %>
<%= cuisine.cuisine_name %>
<% end %>
</div>
<p><%= f.submit %></p>
<% end %>
The development log shows as below.
Started PUT "/testers/3" for 127.0.0.1 at 2014-11-27 16:53:31 -0700
Processing by TestersController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"5awCMjqwUSHaByj1XFDs5UKZUjyvMoigB88NZCFWgSE=", "tester"=> {"cuisine_ids"=>["3", "6"]}, "commit"=>"Update Tester", "id"=>"3"}
User Load (0.3ms) SELECT `testers`.* FROM `testers` WHERE `testers`.`id` = 3 LIMIT 1
Cuisine Load (0.4ms) SELECT `cuisines`.* FROM `cuisines` WHERE `cuisines`.`id` = 3 LIMIT 1
(0.1ms) BEGIN
SQL (0.2ms) INSERT INTO `ratings` (`created_at`, `created_by`, `cuisine_id`, `updated_at`, `tester`, `tester_id`) VALUES ('2014-11-27 23:53:31', NULL, NULL, '2014-11-27 23:53:31', NULL, 3)
(0.4ms) COMMIT
Rendered text template (0.0ms)
Completed 200 OK in 15ms (Views: 0.3ms | ActiveRecord: 3.8ms)
Couple of issues here.
1. Cuisine_ids are not getting inserted in the ratings table
2. If I have combination of tester_id =1 and cuisine_ids = [2,3] already in the join table then it does nothing. I would like to insert again the same values. that is I would like to allow insert statement to work for inserting duplicate entries. That is how my ratings work.
3. If I have combination of tester_id= and cuisine_ids= [1,2,3] and if I select cuisine_ids=[2,3], then it somehow, rails deletes the cuisine_ids[1,2,3] and again inserts [2,3]. so firstly it executes
1.DELETE from ratings where tester_id=1 (and then runs the insert again)
All I want to do is to save the records which the users select using check boxes in the join table. I want to allow duplicates (for tester_id and cuisine_ids combination) in that join table. This join table might resemble to transaction tables i.e. like one product might have repeated/recurring orders by same customer. However, the entire row will still remain unique because rails has its own primary key on each table.
Let me know if you need more information. Someone please help!!!!
Thanks
I need to know more about your data model but I can provide some general guidance here.
class Cuisine < ActiveRecord::Base
attr_accessible :cuisine_name, :id, :cuisine_id
attr_accessor :tester, :cuisine_ids
has_many :testers, :through => :ratings
has_many :ratings
First, adding ":id" to attr_accessible doesn't make sense. You don't need it as it would give people the ability to update a record's id. I'm not sure what "cuisine_id" is, it doesn't make sense that it would be in the cuisines table.
You definitely don't need attr_accessor. And you should add inverse relationships.
So here's where we're left:
class Cuisine < ActiveRecord::Base
attr_accessible :cuisine_name
has_many :ratings, :inverse_of => :cuisine
has_many :testers, :through => :ratings
Next up is Tester:
class Tester < ActiveRecord::Base
attr_accessible :tester_name, :id, :tester_id
attr_accessor :cusines
has_many :cusines, :through => :ratings
has_many :ratings
Again, your attr_accessible is confusing. You also have misspelled "cuisine". Finally, you don't need the attr_accessor and, again, it will actually "hide" the real "cuisines" relationship. Here's what we end up with:
class Tester < ActiveRecord::Base
attr_accessible :tester_name
has_many :ratings, :inverse_of => :tester
has_many :cuisines, :through => :ratings
Finally, ratings. This is simple and actually looks good, but it strikes me that there's probably at least some sort of "rating" attribute that should be in attr_accessors. Since I don't know what's there, let's just add inverse relationships:
class Rating < ActiveRecord::Base
belongs_to :tester, :inverse_of => :ratings
belongs_to :cuisine, :inverse_of => :ratings
Having those correct will make fixing the rest of it possible.
Looking at your ratings controller, it's kind of confusing. I have no idea what the "ratings" action should do. You're mixing plurals and singulars and all that. You have "cuisine" misspelled in another way there. Let's start with the view:
<h3>Review:</h3>
<% for cuisine in Cuisine.find(:all) %>
<div>
<%= check_box_tag("tester[cuisine_ids][]", cuisine.id) %>
<%= cuisine.cuisine_name %>
</div>
<% end %>
<p><%= f.submit %></p>
<% end %>
Presumably there's a "form_for" that you didn't include. I have done the minimal needed to get this to at least render properly. It's still not exactly what you want as it won't allow for updates.
Back to the controller, what is "ratings" supposed to do? Is that your "new" action?
class RatingsController < ApplicationController
def ratings
#ratings=Rating.new
end
def create
#tester= Tester.new(params[:tester])
params[:tester][:cuisine_ids].each do |tester|
#cus=#tester.ratings.build(:tester_id => tester)
#cus.save
end
end
That's a general cleanup. You still aren't saving "#tester" or doing anything else after the create. If you start with a general resource scaffold for testers you can do this pretty easily. But with these issues fixed you can at least start making some headway.
As I said in the comment above, though, you would be wise to put this aside, go through a tutorial, and then revisit this.
i've been searching through similar questions but i still don't get how implement this relationship. I have of course three models :
class Recetum < ActiveRecord::Base
attr_accessible :name, :desc, :duration, :prep, :photo, :topic_id
has_many :manifests
has_many :ingredients, :through => :manifests
end
class Ingredient < ActiveRecord::Base
attr_accessible :kcal, :name, :use, :unity
has_many :manifests
has_many :recetum, :through => :manifests
end
class Manifest < ActiveRecord::Base
attr_accessible :ingredient_id, :quantity, :receta_id
belongs_to :recetum
accepts_nested_attributes_for :ingredient
belongs_to :ingredient
end
Recetum would be a recipe (typo when scaffolding), this recipe may have one or more ingredients (already on the db). So when i create a new Recetum, i need the new recetum to be created and one record inserted in manifest for each ingredient entered by the user.
I would need some help now with views and controllers, how do i create the form for recetum with fields for the ingredients and more important what do i have to modify recetum controller.
Any suggestions or help would be very much appreciated as this part is crucial for my project, thanks in advance.
You have a couple options, and mainly they depend on what you want to do in your view. Do you want to display a set number of max_ingredients or do you want it to be completely dynamic? The dynamic case looks better for the user for sure, but it does make for some more complicated code.
Here is a good RailsCast which explains how to do it dynamically via JavaScript:
http://railscasts.com/episodes/74-complex-forms-part-2
Unfortunately, not everyone runs with JavaScript enabled so you may want to consider doing it the static way.
Firstly, I don't think you need accepts_nested_attributes_for in your Manifest model. However, I do think you need it in your Recetum model. If you're going the static route, you'll probably want to set a reject_if option too.
accepts_nested_attributes_for :manifests, reject_if: :all_blank
Once you do this, you'll need to add manifests_attributes to your attr_accessible.
With the static route, you'll need to prebuild some of the manifests. In your new controller you'll want something like this:
max_ingredients.times do
#recetum.manifests.build
end
In your edit and the error paths of your create and update, you may want:
(max_ingredients - #recetum.manifests.count).times do
#recetum.manifests.build
end
Finally, your view will need some way to set the ingredient. I'll assume a select box for now.
f.fields_for :manifests do |mf|
mf.label :ingredient_id, "Ingredient"
mf.collection_select :ingredient_id, Ingredient.all, :id, :name
You'll want to add some sort of formatting through a list or table probably.
Hopefully, that's enough to get you started.
I am trying to get the attributes of the objects after calling a .where query. The query is the following:
#matchers = TutoringSession.where(:begin_time_hour => 21).limit(5)
I get an array of tutoring sessions as a result. But I would like to be able to return only specific attributes of each of the matching tutoring sessions. So I have the following code in my view:
#matchers.each do |matcher|
matcher.begin_time_hour
end
Instead of listing each of matcher's begin_time_hour attributes, it all of the attributes for each matcher object. I have experimented with this block trying "puts matchers.begin_time_hour," and have also tried using partials to solve this problem, however I keep running into issues. If I ask #matcher.class, it says, it is ActiveRecord::Relation object. I thought it would be a TutoringSession object.
Here are my models, in case this helps.
require 'date'
class TutoringSession < ActiveRecord::Base
belongs_to :refugee
belongs_to :student
before_save :set_day_and_time_available, :set_time_available_hour_and_day
attr_accessor :begin_time, :book_level, :time_open
attr_accessible :time_open, :day_open, :tutoring_sessions_attributes, :page_begin, :begin_time
end
and my other class is the following
require 'date'
require 'digest'
class Refugee < ActiveRecord::Base
has_many :tutoring_sessions
has_many :students, :through => :tutoring_sessions
accepts_nested_attributes_for :tutoring_sessions, :allow_destroy => true
attr_accessible :name, :email, :cell_number, :password, :password_confirmation, :day_open, :time_open, :tutoring_sessions_attributes
end
Please let me know if you need more info. Thanks for the help!
It looks like you're not outputting anything to the view. By calling
#matchers.each do |matcher|
matcher.begin_time_hour
end
you get the result from running the loop, which is the relation, instead of the data. You are accessing begin_time_hour, but you aren't doing anything with it. You'd need something more like this to display the begin_time_hour fields.
<% #matcher.each do |matcher| %>
<%= matcher.begin_time_hour %>
<% end %>
By the way, #matchers should be an ActiveRecord::Relation object, a representation of the sql query that will be generated from the where and limit clauses. Calling all on the relation with make it an array of TutoringSession objects
#matchers = TutoringSession.where(:begin_time_hour => 21).limit(5).all
Calling each implicitly runs the query and iterates over the TutoringSession objects, so you shouldn't need to worry about that though.
I'm trying to model this inheritance for a simple blog system
Blog has many Entries, but they may be different in their nature. I don't want to model the Blog table, my concern is about the entries:
simplest entry is an Article that has title and text
Quote, however, does not have a title and has short text
Media has a url and a comment...
etc...
What is a proper way to model this with Ruby on Rails? That is
Should I use ActiverRecord for this or switch to DataMapper?
I would like to avoid the "one big table" approach with lots of empty cells
When I split the data into Entry + PostData, QuoteData etc can I have belongs_to :entry in these Datas without having has_one ??? in the Entry class? That would be standard way to do it in sql and entry.post_data may be resolved by the entry_id in the postdata table.
EDIT: I don't want to model the Blog table, I can do that, my concern is about the entries and how would the inheritance be mapped to the table(s).
I've come across this data problem several times and have tried a few different strategies. I think the one I'm a biggest fan of, is the STI approach as mentioned by cicloon. Make sure you have a type column on your entry table.
class Blog < ActiveRecord::Base
# this is your generic association that would return all types of entries
has_many :entries
# you can also add other associations specific to each type.
# through STI, rails is aware that a media_entry is in fact an Entry
# and will do most of the work for you. These will automatically do what cicloon.
# did manually via his methods.
has_many :articles
has_many :quotes
has_many :media
end
class Entry < ActiveRecord::Base
end
class Article < Entry
has_one :article_data
end
class Quote < Entry
has_one :quote_data
end
class Media < Entry
has_one :media_data
end
class ArticleData < ActiveRecord::Base
belongs_to :article # smart enough to know this is actually an entry
end
class QuoteData < ActiveRecord::Base
belongs_to :quote
end
class MediaData < ActiveRecord::Base
belongs_to :media
end
The thing I like about this approach, is you can keep the generic Entry data in the entry model. Abstract out any of the sub-entry type data into their own data tables, and have a has_one association to them, resulting in no extra columns on your entries table. It also works very well for when you're doing your views:
app/views/articles/_article.html.erb
app/views/quotes/_quote.html.erb
app/views/media/_media.html.erb # may be medium here....
and from your views you can do either:
<%= render #blog.entries %> <!-- this will automatically render the appropriate view partial -->
or have more control:
<%= render #blog.quotes %>
<%= render #blog.articles %>
You can find a pretty generic way of generating forms as well, I usually render the generic entry fields in an entries/_form.html.erb partial. Inside that partial, I also have a
<%= form_for #entry do |f| %>
<%= render :partial => "#{f.object.class.name.tableize}/#{f.object.class.name.underscore}_form", :object => f %>
<% end %>
type render for the sub form data. The sub forms in turn can use accepts_nested_attributes_for + fields_for to get the data passed through properly.
The only pain I have with this approach, is how to handle the controllers and route helpers. Since each entry is of its own type, you'll either have to create custom controllers / routes for each type (you may want this...) or make a generic one. If you take the generic approach, two things to remember.
1) You can't set a :type field through update attributes, your controller will have to instantiate the appropriate Article.new to save it (you may use a factory here).
2) You'll have to use the becomes() method (#article.becomes(Entry)) to work with the entry as an Entry and not a subclass.
Hope this helps.
Warning, I've actually used Media as a model name in the past. In my case it resulted in a table called medias in rails 2.3.x however in rails 3, it wanted my model to be named Medium and my table media. You may have to add a custom Inflection on this naming, though I'm not sure.
You can handle this easily using ActiveRecord STI. It requires you to have a type field in your Entries table. This way you can define your models like this:
def Blog > ActiveRecord::Base
has_many :entries
def articles
entries.where('Type =', 'Article')
end
def quotes
entries.where('Type =', 'Quote')
end
def medias
entries.where('Type =', 'Media')
end
end
def Entry > ActiveRecord::Base
belongs_to :blog
end
def Article > Entry
end
def Quote > Entry
end
def Media > Entry
end
I'm still a bit of a n00b when it comes to rails, however, I do have a question as to how to go about a multi-model form.
Basically, I have an event, and the user needs to be able to register for the event and provide a credit card for charging the event to. The credit card (I won't be holding the actual data for the CC, authorize.net will, but I need to keep a token representing the card) will live with the user so they can sign up for other events in the future. So, I want the user to be able to edit this in the future, and the card isn't specific to a single event. This doesn't seem like something I'd use nested routes with, does it?
I have a feeling this is fairly simple, but I guess I'm just not entirely sure how to do it. Can I used nested models (not routes) and still update each portion independently?
If I understand your question, then yes you can. I think you mean something like this:
class User < ActiveRecord::Base
has_one :credit_card
end
If that's correct, then the first step is to add this to the User class:
class User < ActiveRecord::Base
has_one :credit_card
accepts_nested_attributes_for :credit_card
end
At this point you could just set up a "users" resource in the routes file and you could edit the credit card through a fields_for method in your edit view:
form_for #user do |f|
f.fields_for :credit_card do |ff|
ff.label :number
ff.text_field :number
end
f.submit
end
Does that help?
Since Formatting is not allowed in comments, I am making a answer for it.
Thanks #twmills for your answer,
I am also new to rails. I have a question, will it work in case where I have following relationship:
class User < ActiveRecord::Base
has_many :credit_cards, :dependent => :destroy
accepts_nested_attributes_for :credit_card
end
class CreditCards < ActiveRecord::Base
belongs_to :user
end
In above case, you can't create a CreditCard object unless you have parent user. Will f.fields_for :credit_card do |ff| also create an object of CraeditCard #user to f?
As per my understanding, this is not possible as how will be tell the view, which credit card to edit.
Secondly, On edit, this is fine but can I do something similar at the time of user creation. i.e. getting his credit card information at the time of user creation.