Mutiple selection select boxes with Ruby on Rails - ruby-on-rails

I'm using 4 tables to fill a chart, similar to these:
#colors #types #fuels
----------------- --------------------- -------------------
| ID | Color | | ID | Type | | ID | Fuel |
----------------- --------------------- -------------------
| 1 | 'Red' | | 1 | 'SUV' | | 1 | 'Gasoline' |
| 2 | 'Green' | | 2 | 'Truck' | | 2 | 'Diesel' |
| 3 | 'Blue' | | 3 | 'Sports Car' | | 3 | 'Electric' |
| 4 | 'Yellow' | | 4 | 'Compact' | | 4 | 'Hybrid' |
----------------- --------------------- -------------------
The last table is an orders table, similar to this:
#orders
--------------------------------------------------------
| order_id | color_id | type_id | fueld_id | purchases |
--------------------------------------------------------
| 1 | 2 | 1 | 4 | 2 |
| 2 | 1 | 4 | 1 | 4 |
| 3 | 2 | 2 | 2 | 6 |
| 4 | 4 | 1 | 4 | 2 |
| 5 | 1 | 4 | 2 | 1 |
| 6 | 3 | 3 | 3 | 1 |
| 7 | 3 | 3 | 3 | 2 |
| 8 | 2 | 1 | 1 | 2 |
--------------------------------------------------------
I have a controller that polls data from them all to make the chart. So far so good. Now, I want to let the user pick one or more attributes from each table, to make a dynamic orders page.
My approach is to show 3 select boxes (listboxes) that could allow the user to make a selection, and based on this, the #orders table would be modified. The modifications would land on different action, say:
def newtable
...
end
I know how to do this via SQL, but I'm not too sure how to properly show these listboxes using RoR. My idea is to pick one, several, or ALL the elements of each table.
Would form_for do the trick? I was trying to use it, but I don't have a model to base the query on, and I'm not sure how to create one (or if that approach is actually viable).
Thanks.

Well I'm Not Familiar with Rails 4 yet,but i can provide an answer as per Rails 3.
First Make Necessary Associations.
And In your Orders controller define one new method like
def create
----your stuff---
end
In your Order Form page:
<%= form_tag :action => 'create' %>
<%= collection_select :order,:color_id, #colors,'id','Color',{:label=> 'Select a Color',:prompt=> 'Select'} %>
<%= collection_select :order,:type_id, #types,'id','Type',{:label=> 'Select a Type',:prompt=> 'Select'} %>
<%= collection_select :order,:fuel_id, #fuels,'id','Fuel',{:label=> 'Select a Fuel',:prompt=> 'Select'} %>
<%= submit_tag "Create" %>
Hope this works.
Note: This is just a sample code for your understanding.

<%= f.select(:color, #color.collect {|p| [ p.name, p.id ] },
{ :prompt => "Please select"},
{ :multiple => true, :size => 4 }) %>
To configure your controller to accept multiple parameters: Click Me
You can create a separate model as a ruby class to handle this if you wish, but only if you find the other models getting too cramped. Hope that helps

Related

Rails validation In attribute table

i am new to ROR.
i am building a classified ads app, i have the following tables in my database:
(some fields have been removed for simplicity)
Table Uers
This table stores all the users.
user_id
name
email
password
Table Ads
This table stores all the ads.
ad_id
users_user_id (FK)
title
desc
cat_id (FK)
created_at
Sample data:
------------------------------------------------------------------------------
| ad_id | users_user_id | title | desc | cat_id | created_at |
------------------------------------------------------------------------------
| 1 | 1 | iphone 4 | brand new | 2 | 30-11-2015 |
------------------------------------------------------------------------------
Table categories
This table stores all the available categories. cat_id in the ads table relates to cat_id in this table.
cat_id
category
parent_cid
Sample data:
-------------------------------------------
|cat_id| category | parent_cid |
-------------------------------------------
|1 | Electronics | NULL |
|2 | Mobile Phone | 1 |
|3 | Apartments | NULL |
|4 | Apartments - Sale | 3 |
-------------------------------------------
Table ads_attribute
This table contains all the available attributes for a particular category. Relates to categories table.
attr_id
cat_id (FK)
attr_label
attr_name
Sample data:
-----------------------------------------------------------
|attr_id | cat_id | attr_label | attr_name |
-----------------------------------------------------------
|1 | 2 | Operating System | Operating_System |
|2 | 2 | Is Touch Screen | Touch_Screen |
|3 | 2 | Manufacturer | Manufacturer |
|4 | 3 | Bedrooms | Bedrooms |
|5 | 3 | Total Area | Area |
|6 | 3 | Posted By | Posted_By |
-----------------------------------------------------------
Table ads_attr_value
This table stores the attribute value for each ad in ads table.
attr_val_id
attr_id (FK)
ad_id
attr_val
Sample data:
---------------------------------------------
|attr_val_id | attr_id | ad_id | attr_val |
---------------------------------------------
|1 | 1 | 1 | Ios 8 |
|2 | 2 | 1 | 1 |
|3 | 3 | 1 | Apple |
---------------------------------------------
What is the best way (the rails way) to validate the data before storing it in the the ads_attr_value table, given the fact that the values would be in select fields and the user can change them easily for example from Ios 8 to "blabla".
I've thought of storing all the possible values for each attribute in a new table and then check if a value sent by the user exist in that table before storing it in the ads_attr_value. what do you think? I am sure that there is a better way.thanks for sharing.
The rails way would probably to define your relationships with ActiveRecord associations : http://guides.rubyonrails.org/association_basics.html.
Therefore you could easily define on your model
class AdsAttrVal < ActiveRecord::Base
belongs_to :ad
validates :ad, presence: true
end
However please keep in mind that rails way to store an id of the table is to name it "id" and not "model_id" like you did ("user_id", "id"). My exemple suppose that the rails way is respected...
You have to specify the validations you want inside <yourModel>.rb (the model file) . For exame if you want to validate if ad_id is a number you should add the numericality parameter in the validates statement, see below:
class AdsAttrValue < ActiveRecord::Base
validates :ad_id, numericality: true
#validate if add_att_value has the permitted values
validate :myCustomValidation
def myCustomValidation
#your logic of validation goes here
#you can access here all the fields from this object recently created
if attr_val == something
#do something
end
end
end
See that validations from rails have an s at the end (validates), and your own written validations do not have (validate).
This validations are executed when creating the object before storing in database in order to see if it complies the validations and not stored it it does not comply. You can add errors in your own validation to let the user know what gone wrong. Go further with this reading of validations in ruby on rails

ruby on rails - how to take only take one row

Restaurant Load (1.5ms) SELECT * FROM "restaurants" INNER JOIN
"restaurant_branches" ON "restaurant_branches"."restaurant_id" =
"restaurants"."restaurant_id"
+----------+---------+---------+---------+----------+---------+----------+---------+---------+---------+---------+---------+---------+---------+---------+-------+
| resta... | res_... | res_... | crea... | updat... | user_id | resta... | addr...
| addr... | addr... | addr... | addr... | addr... | numb... | numb... | email |
+----------+---------+---------+---------+----------+---------+----------+---------+---------+---------+---------+---------+---------+---------+---------+-------+
| 27 | DOGG... | WE S... | 2014... | 2014-... | 4 | 28 | 405 ...
| | CHICAGO | IL | 60666 | USA | | | |
| 27 | DOGG... | WE S... | 2014... | 2014-... | 4 | 29 | 111 ...
| | CHICAGO | IL | 60661 | USA | | | |
+----------+---------+---------+---------+----------+---------+----------+---------+---------+---------+---------+---------+---------+---------+---------+-------+
As you can see, I have two records for record 27. This is from a joined
table between restaurants and restaurant_branches. How would I approach
this in a view so that when I select a record on my index.html.erb file
when it gets routed to the show.html.erb file it'll only take one row of
that record and only show me one branch instead of 2?
Thank you for any help.
The two records are different, so keep them separate and list both. It's difficult to say which fields are different from the question. Based on the query, I'm assuming they are restaurant_branches fields that are different.
If it's the restaurants that you want to show/edit then use just Restaurant.all however you want to limit. If however you want to edit the restaurant_branches then introduce a RestaurantBranchesController and have a link for the branches separate.
Something like (in erb):
<%= restaurant.id %>
<% restaurant.restaurant_branches.each do |rb| %>
<%= link_to 'Some branch', rb %><br />
<% end -%>
Then the link_to(rb) should link you to RestaurantBranchesController#show action for the particular restaurant_branch.
Collection
Further to what #vee was suggesting, it seems to me that you're calling a collection of data from ActiveRecord. A collection basically means you're going to receive a multitude of objects back, rather than just one record
I'd imagine you have your models set up as follows:
#app/models/restaurant.rb
Class Restaurant < ActiveRecord::Base
has_many :branches, class_name: "RestaurantBranch"
end
#app/models/restaurant_branch.rb
Class RestaurantBranch < ActiveRecord::Base
belongs_to :restaurant
end
This will give you the ability to call the following:
#restaurant = Restaurant.find params[:id]
#restaurant.branches #-> returns the collection
--
Limit
The way to fix this will depend on what you're trying to show.
Typically, you can use something like limit to retrieve a single record, like so:
#restaurant.branches.limit(1)
Like most things in life, this will be much simpler to resolve if you define what you want to limit the results for - what's the purpose?

How to delete record from only associated table with has_and_belongs_to_many relation ship

I have two model hotel and theme and both has has_and_belongs_to_many relationship
and third table name is hotels_themes, So I want to delete record only from third tables hotels_themes.
hotels_themes;
+----------+----------+
| hotel_id | theme_id |
+----------+----------+
| 8 | 4 |
| 9 | 5 |
| 11 | 2 |
| 11 | 4 |
| 11 | 6 |
| 12 | 2 |
| 12 | 5 |
+----------+----------+
I want to delete record which match hotel_id and theme_id.
Like sql query delete from hotels_themes where hotel_id=9 and theme_id=5
Use the method delete added to HABTM collections:
hotel = Hotel.find(hotel_id)
theme = Theme.find(theme_id)
hotel.themes.delete(theme)
You just need to empty out the association on either model instance depending on what you are trying to remove. For example:
hotel.themes = []
# or
theme.hotels = []

Merging two Tables using Scaffold & Rails (Rails noob)

I am new to coding (never taken a CS class and have a very very minimalist understanding of the MVC architecture) and working on a test project to learn it :-) I want to setup some tables tables:
Table 1:
Table_1 ID | Name | Attribute_1 | Attribute_2 | Attribute_3 | etc
1 | Blah | attribute 1 | attribute 2 | attribute 3 |
Table 2:
Table_2 ID | Skill |
1 | nun_chucks |
2 | bow |
3 | arrow |
Table 3:
Table_3 ID | Primary_1 ID | Primary_2 ID |
1 | 1 | 1 |
2 | 1 | 2 |
3 | 1 | 3 |
And then be able to visualize the data so it reads like:
Name | nunchucks, bow, arrow | attribute 1 | attribute 2 | attribute 3 |
I have used Scaffold to create the MVC for Table 1 & 2 and have the #page for each one respectively. I am not sure how to combine them to create table 3 and then make the data show as I am asking.
Thanks!
This is a good reference for what you're doing: http://guides.rubyonrails.org/association_basics.html
INNER JOIN is what you want which is a database operation.
Take a look in your database servers manual and read up on it.
Essentially it takes two tables, joins them by a given column (for instance, Table_2.ID and Table_3.ID) and spits out a summary of both tables joined leaving out columns that don't match across the tables.
Given your example,
and the following contoller in Rails 3
class SomeController < ActionController
def show
#table_1 = Table1.find(params[:id],:include => :table2)
# Table1 and Table2 are your models
# where table2 would be your has_many_and_belongs_to_many assoc in Table1
end
end
you could write this up in show.html.erb like
<%= #table_1.name %>
<%= #table_1.table_2.map(&:skill) %>
<%= #table_1.attribute_1 %>
<%= #table_1.attribute_2 %>
<%= #table_1.attribute_3 %>

NoMethodError in Ruby on Rails

I've encountered the following error while trying to create a blogging application. Any ideas why?
NoMethodError in Articles#show
Showing app/views/articles/show.html.erb where line #1 raised:
undefined method `title' for []:Array
Extracted source (around line #1):
1: <h2><%= #article.title %></h2>
2:
3: <% if #article.category %>
4: <p class="category">
From my limited understanding it's trying to tell me that there is no 'title' field in my 'article' database table, however as you can see from the desc below there is cleary a 'title' field!
mysql> desc articles;
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | YES | | NULL | |
| title | varchar(255) | YES | | NULL | |
| synopsis | text | YES | | NULL | |
| body | text | YES | | NULL | |
| published | tinyint(1) | YES | | 0 | |
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
| published_at | datetime | YES | | NULL | |
| category_id | int(11) | YES | | 1 | |
+--------------+--------------+------+-----+---------+----------------+
10 rows in set (0.01 sec)
Help?!
Bernard
Ps. hope the formatting of the table above holds up... doesn't seem to look very good in the preview!
Controller code for relevant call as follows.
def show
if is_logged_in? && #logged_in_user.has_role?('Editor')
#article = Article.find(params[:id])
else
#article = Article.find_all_by_published(params[:id], true)
end
respond_to do |wants|
wants.html
wants.xml { render :xml => #article.to_xml }
end
end
I think you're trying to access the title element directly from the array. You'll need to iterate through each of the objects before you can access the properties.
for #article in #articles do |a|
<h2><%= a.title %></h2>...
end
Just make sure to have in your controller...
#articles = Article.find(:all, :conditions => '...')
Update:
This part of your code returns a collection.
#article = Article.find_all_by_published(params[:id], true)
It looks like you're assigning an empty array to #article in your controller. It should instead be an instance of Article (if that's your model name). Can you paste your controller code?

Resources