add external data at new record creation time

In my project i require a bit.ly link for each new product entered in the database. Please guide me on how to do this?

Note: I am using a standard rails app with basic actions to test this code

I plan on writing a helper function which will be able to take the id for the new record and return the link.

Here are my questions:

1) Should I add the link column in the same table as the product or create a new table with just a vehicle id and its corresponding bit.ly link?

2) Where in the controller should i make the call to create the link as a product id will be required before the link can be generated and I am not 100% sure where exactly in the controller when creating a new record is the new record id available to be accessed.

Apologies in advance if the questions is not very clear but any help will be greatly appreciated.

Quee WM wrote:

I plan on writing a helper function which will be able to take the id for the new record and return the link.

Using a "helper" function implies that the coding will trigger as the template is being rendered. If this is the case, you don't need an entry in the database. Just write the helper to use the item id to look up the item and generate the link from the item information.

However, if the link/URL is needed elsewhere (perhaps outside the Rails app) and therefore needs to be stored in the database, then I'd suggest you just create an extra field (bit_ly_url perhaps). This is assuming that each vehicle has a unique URL.

As for the code that generates the URL - I'd create a custom ruby class to do that. Put the code in the lib folder.

So for example, say you create a class CreateURL with a class method of bit_ly_for_vehicle, you can then create a vehicle instance method to call the CreateURL method and this can be triggered via a call back (e.g. before_save)

So

class Vehicle < ActiveRecord::Base   before_save update_bit_ly_url

  def update_bit_ly_url     bit_ly_url = CreateURL.bit_ly_for_vehicle(self.id)   end end

Rob Nichols wrote:

class Vehicle < ActiveRecord::Base   before_save update_bit_ly_url

  def update_bit_ly_url     bit_ly_url = CreateURL.bit_ly_for_vehicle(self.id)   end end

Actually - just spotted that you'd have to use after_save or information other than the id to generate the url, as on create, the id doesn't exist until the object is saved. Also CreateUrl is probably a better ruby class name.

Thanks for the help. That put me on the right path.

Back for some more help.

I added the following code to the model of the vehicle

class Vehicle < ActiveRecord::Base   after_save :update_bit_ly_url

  def update_bit_ly_url     bit_ly_url = CreateUri::bit_ly_for_vehicle(self.id)     puts bit_ly_url   end end

had to change CreateUri. to CreateUri:: as it was not recognizing CreateUri.

maybe I have not written the class properly or have not included it in the correct manner.

Now this is the error i get.

NameError (uninitialized constant Vehicle::CreateUri):   app/models/vehicle.rb:22:in `update_bit_ly_url'   app/controllers/vehicles_controller.rb:46:in `create'

Any ideas?

Your change from . to :: is a red herring. The method call semantics of . and :: are the same. The error means that your CreateUri class is not being loaded. Check the way it is loaded (by Rails autoloading, by a require statement, etc).

Also, I would have structured the url creation class differently. First, CreateUri is a poor class name because it is too generic. Second, passing an integer (the vehicle id) would require the CreateUri class to know far too much about what that integer represents, thus coupling it conceptually to the Vehicle class. These problems are apparent in the need for the awkward method name "bit_ly_for_vehicle". The Bitly url generator should accept a url and return a url, as this is the interface provided by the service itself (bit.ly's API).

Given that the Bitly API requires authentication, I would prefer something like:

Bitly.new(username, api_token).shorten(url_for(@vehicle)).short_url

"Shorten the url for the vehicle" reveals the code's intention nicely.

In fact, and speaking of reuse, this is precisely what the Bitly gem provides (http://github.com/philnash/bitly).

This does not address performance and reliability concerns with the network, the Bitly service and etc., but it is at least a good start. Also, do note that this will require url_for in your model. Google should tell you how to make this happen.