1

I've built a lookup table in my Rails application.

It is a table that stores lookup text values for drop-down pickers or possibly check boxes. I want the lookup table to have a view associated so the values can be easily edited. I also may want to share lookup values among multiple models for a single field in the future.

So far I've managed to get it to work for the selection of values, but then displaying the text value again on a show or index view has been problematic.

This is how I built the lookup table

rails g scaffold Lookup field_name lookup_text table_name note

In the edit.html.erb where there is a lookup on a field, I've got code like this, which works and allows me to pick from a list.

<div class="field">
    <%= f.label :status %><br />
    <%= f.collection_select :status, Lookup.find(:all,:conditions => ["table_name = 'course' and field_name = 'status'"]), :id, :lookup_text, include_blank: true,:prompt => "Status" %>
</div>

That all works fine. When I try to display it back I cannot find the correct syntax. The best I have found is this: (in the controller)

@status = Lookup.where(:id => @course.status).pluck(:lookup_text)

(in the view)

<p>
  <b>Status:</b>
  <%= @status %>
</p>

I think I am getting the entire object. It displays like this:

Status: ["Active"]

My questions are: (1) How do I display the value only? (2) Is this the best approach?

I've had a look at these and other SO questions, but none are really what I am looking for:

Rails Polymorphic with Lookup Table

Implementing a lookup table in Rails

EDIT OK this works, but it doesn't look like it is the correct solution. Has anyone got a better way of doing this?

@status = Lookup.where(:id => @course.status).pluck(:lookup_text)[0]
Community
  • 1
  • 1
port5432
  • 5,889
  • 10
  • 60
  • 97

1 Answers1

1

Just another way to show the value is @status = Lookup.find(@course.status).lookup_text

Why not to try use classes for different lookups:

class CourseStatus < ActiveRecord::Base
  set_table_name "lookups"
  default_scope where("table_name = 'course' and field_name = 'status'")
end

class Course
  belongs_to :course_status
end

You then can use:

CourseStatus.all # e.g. to fill select options
Course.first.course_status.lookup_text # => "Active" or smth else

Or without classes:

class Lookup
  def self._by_table_and_field(table, field)
    ['table_name = ? and field_name = ?', table, field]
  end

  scope :by_table_and_field, lambda { |table, field| 
    where(Lookup._by_table_and_field(table, field))
  }
end

class Course
  belongs_to :status, class_name: 'Lookup', conditions: Lookup._by_table_and_field('course', 'status')
end

Lookup.by_table_and_field('course', 'status').all
Course.first.status.lookup_text
Aleksei Chernenkov
  • 991
  • 1
  • 8
  • 23
  • Thanks for your answer. I see that is an interesting approach! – port5432 Oct 25 '12 at 15:16
  • What if just declare belongs_to like this: `class Course; belongs_to :status, class_name: 'Lookup'; end` and then: `Course.first.status.lookup_text`. You can also define scope on Lookup table to retrieve lookup rows for specific table/field pair nice way. – Aleksei Chernenkov Oct 25 '12 at 15:27
  • Please see edited post. You can go further and make it possible to access to `status` field without explicit `.lookup_text` part (just `Course.first.status` # -> 'Active'), this will make your code more DRY. – Aleksei Chernenkov Oct 25 '12 at 15:50
  • I'm not sure code is correct. I wrote it right in submit form =) Sorry for possible mistakes – Aleksei Chernenkov Oct 25 '12 at 15:58
  • The without classes solution is ever better. Thanks a lot! Feel free to vote up the question if you think it is a good one. – port5432 Oct 25 '12 at 20:45