Hey all Im trying to get has_many :through relationship working, as i head its better and more robust that HABTM. I have the following tables/objects... class Currency < ActiveRecord::Base has_many :product_prices has_many :products, :through => :product_prices end class Product < ActiveRecord::Base has_many :product_prices has_many :currencies, :through => :product_prices end class ProductPrice < ActiveRecord::Base belongs_to :product belongs_to :currency end Is that the correct configuration for what is effectivly a HABTM relationship? If not could somone please point me in the right direction!! Furthermore, if i wanted to submit data into the product prices table/object, how would i do that? The same was as any other commit? Object.new(params[:object]) ? Cheers all Tim -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
HABTM does have its use. If your domain does not need any attributes other than the foreign keys of the tables that are connected then HABTM is good enough. In this case the association class is just a join table. When your application demands that other attributes needs to be persisted that belongs to the association class then you have to go for the has_many :through relationship.> > I have the following tables/objects... > > class Currency < ActiveRecord::Base > has_many :product_prices > has_many :products, :through => :product_prices > end > > class Product < ActiveRecord::Base > has_many :product_prices > has_many :currencies, :through => :product_prices > end > > class ProductPrice < ActiveRecord::Base > belongs_to :product > belongs_to :currency > end > > Is that the correct configuration for what is effectivly a HABTM > relationship? If not could somone please point me in the right > direction!!This is correct. Furthermore, if i wanted to submit data into the product prices> table/object, how would i do that? The same was as any other commit? > Object.new(params[:object]) ?When a product is associated to the currency, you can do: product_price = ProductPrice.new product_price.attribute1 = params[:attribute1] and so on. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
I may be missing somthing here, but in my controller i have def add @currencies = Currency.find(:all, :conditions => [''currency_active = 1'']) unless request.post? # cast a new product object @product = Product.new @prices = @product.product_prices.new else @product = Product.new(params[:product]) @prices = @product.product_prices.new(params[:prices]) if @product.save # do the saving... end end end And in my view (this is an extract just to do with the currencys...)... <% for currency in @currencies -%> <div class="table-row auto-height left-align"> <div class="column general"><label><%=currency.currency_name%></label></div> <div class="column general"><%=text_field :prices, :unit_price %></div> </div> <% end -%> But when i submit, it sets both values to the same value. I know i need somthing like... params[:prices][1][:unit_price] and so on, with array indexes, but how do achive this in the HTML form with the rails helpers? Ive tried all sorts!! Any help would be welcomed Cheers Tim -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
> > > But when i submit, it sets both values to the same value. I know i need > somthing like... params[:prices][1][:unit_price] and so on, with array > indexes, but how do achive this in the HTML form with the rails helpers? > Ive tried all sorts!!What version of Rails are you using? --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
> What version of Rails are you using?Im using version 1.1.6 -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
On 10/23/06, Tim Perrett <rails-mailing-list-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> > > > What version of Rails are you using? > > Im using version 1.1.6Instead of using: @prices = @product.product_prices.new(params[:prices]) Try this: @prices = ProductPrice.new(params[:prices]) @product.product_prices << @prices --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
> @prices = ProductPrice.new(params[:prices]) > @product.product_prices << @pricesOk cool, cheers, i''ll give a whirl. Effectivly, rather than setting a new object, its appending the posted paramaters to the product_prices in the @product object. Thats all well and good, i understand that (i think) but in my view code, how do i set it up so that is posts two different values from a display loop? In order for me to have say, a euro price and a sterling price, i would want to have the form effectivly generate somthing like <input type="text" name="prices[:unit_price][1]" value="" /> <input type="text" name="prices[:unit_price][2]" value="" /> That would work wouldnt it? As it would then just pass back into the prices object which would append onto my product object? Cheers for any help Tim -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
price, i would want to have the form effectivly generate somthing like> > <input type="text" name="prices[:unit_price][1]" value="" /> > <input type="text" name="prices[:unit_price][2]" value="" />So you have both Euro and Sterling price displayed on the page as text fields? And you want to populate those into your product_prices table? @prices = ProductPrice.new(params[:euro_price]) @product.product_prices << @prices @prices = ProductPrice.new(params[:sterling_price]) @product.product_prices << @prices Will this solution work for your scenario? --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
Thanks for the suggestion, but it wouldnt unfortunatly, As for instance, the currencys are dynamic, so in another setup you might have USD, Yen, GBP and Euro''s, so what you would idealy do is have it in some kind of object and insert the rows dynamicly, but ive no idea on the syntax? Possibly, if i had it in an array, or hash, i could loop through them doing the appends and saves. But that to me, seems not to be a clean rails way. I know what i want to achiveve, but im not sure on the best way to do it? cheers Tim -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
How does your screen look like? I really don''t understand what you are saying. Can you explain clearly without making any assumption what you are trying to do?> Possibly, if i had it in an array, or hash, i could loop through them > doing the appends and saves. But that to me, seems not to be a clean > rails way. > > I know what i want to achiveve, but im not sure on the best way to do > it? > > cheers > > Tim > > -- > Posted via http://www.ruby-forum.com/. > > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
Bala Paranj wrote:> How does your screen look like? I really don''t understand what you are > saying. Can you explain clearly without making any assumption what you > are > trying to do?Sure, sorry i appreciate its a little confussing. I have a currencies table in the database, which could hold multiple rows for different currencys. I also have a products table, which details information about products on the system etc etc. Now, one product will have many prices based on the currency - so its effectivly a HABTM, but ive changed it to has_many :through as i heard it was more flexiable. so basicly, the table structure is this: products HABTM currencies, and the join table is product_prices. My models look like this: class Currency < ActiveRecord::Base has_many :product_prices has_many :products, :through => :product_prices end class Product < ActiveRecord::Base has_many :product_prices has_many :currencies, :through => :product_prices end class ProductPrices < ActiveRecord::Base belongs_to :products belongs_to :currencies end So thus, im building an administration where when the client wants to add a new product, they fill in the details, and say that the currencies table has two rows, one for euro, and one for sterling, the add product screen would present two text feilds needing both an inputed price for sterling for that product and one for euro. So you see, when i pass the post back to my controller, how do i handle having two (or more, based on wats in the currencies table) rows to insert into the product_prices table? Hope that a good explanation of it Cheers Tim -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
> > class Currency < ActiveRecord::Base > has_many :product_prices > has_many :products, :through => :product_prices > end > > class Product < ActiveRecord::Base > has_many :product_prices > has_many :currencies, :through => :product_prices > end > > class ProductPrices < ActiveRecord::Base > belongs_to :products > belongs_to :currencies > end > > So thus, im building an administration where when the client wants to > add a new product, they fill in the details, and say that the currencies > table has two rows, one for euro, and one for sterling, the add product > screen would present two text feilds needing both an inputed price for > sterling for that product and one for euro. > > So you see, when i pass the post back to my controller, how do i handle > having two (or more, based on wats in the currencies table) rows to > insert into the product_prices table?Your question basically boils down to "How to create a new :through association?". You can create :through association using the << method. Both Product and Price must be saved before you can use that operator. So, product = Product.create(:name => "DVD") euro_price = Currency.create(:amount => 123) dollar_price = Currency.create(:amount => 99) product.currencies << euro_price product.currencies << dollar_price You can define two fields name euro_price and dollar_price in your view. When the user submits, you can do the above in your action. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---
Ok, i built a solution, id thought id share it back as i thnk you missed the point a bit! Its obviously desirable to run everything from the DB as it then stays dynamic, and your solution of hardcoding :sterling and :euro form feilds, although would work, is inflexible and would mean adding new code if a new currency was added - so over its more work and less agile. So, the solution i came up with was this... -- controller --- def add @currencies = Currency.find(:all) unless request.post? # If this anything BUT a _post request @product = Product.new @prices = @product.product_prices.new else # handle the post # process product post @product = Product.new(params[:product]) @product.valid? # make new var @prices = @product.product_prices # get the prices array and process... params[:prices].map do |key, val| tmp = @product.product_prices.new(params[:prices][key]) tmp.valid? @prices << tmp end # Start the DB transaction # this will raise AR exception if it fails, i.e. the models are not valid begin Product.transaction do # try and save the product model, thus gaining the DB id @product.save! # now, with the id from the product model, save the variable # number of price rows in the product_prices table for price in @prices price.product_id = @product.id end @product.product_prices = @prices @product.save! end rescue => e flash[:error] = e end end end Thats about as clean as i could make it, the functionality isnt repeated anywhere else so i didnt need to break it off into a module. And in my view code: <input id="prices_1_id" name="prices[1][currency_id]" type="hidden" value="1" /> <input id="prices_1_unit_price" name="prices[1][unit_price]" size="30" type="text" /> Using the array type set up, i could then manipulate this with .map do |key, val| so if i added another currency, sav, Yen, then it would just adapt and be ready to take a new currency :) My model objects stayed the same as above. Do you see what i mean? Im not 100% sure this is the best way, but out of everything i tried it seems to work the best, and its reliable in terms of validations and the like! Cheers Tim -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk -~----------~----~----~----~------~----~------~--~---