if you go to www.leapfm.com you'll see each song has a youtube url in parenthesis to the right of it. After gauging feedback I have decided to instead display the genre tags in the parenthesis.
When trying to do this,
I'm getting this error:
Couldn't find Genre without an ID
Extracted source:
def genre_name
#genre = Genre.find(params[:id])
end
def get_last_song
song_controller snippit
def index
if params[:query].present?
#songs = Song.search(params)
get_last_song
genre_name
elsif params[:genre]
#songs = Song.tagged_with(params[:genre]).paginate(:page => params[:page], :per_page => 15)
get_last_song
genre_name
else
#songs = Song.order('id').order('plusminus desc nulls last').paginate(:page => params[:page], :per_page => 15)
##songs = Song.tally.paginate(:page => params[:page], :per_page => 15)
get_last_song
genre_name
end
end
def genre_name
#genre = Genre.find(params[:id])
end
index.html.erb (_song partial) snippit
<div class="title">
<%=link_to image_tag('arrow.gif'), vote_for_song_path(song), :remote => true, :method => :put if controller.action_name == "index" %>
<%= link_to song.title, song %><span class="subtext"> (<%= song.genre_name %>)</span>
</div>
song.rb snippit:
class Song < ActiveRecord::Base
acts_as_voteable
belongs_to :user
has_many :comments, :dependent => :destroy
has_many :genre_songs
has_many :genres, through: :genre_songs
genre.rb
class Genre < ActiveRecord::Base
has_many :genre_songs, :dependent => :destroy
has_many :songs, through: :genre_songs
end
schema snippit
create_table "genre_songs", force: true do |t|
t.integer "genre_id"
t.integer "song_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "genre_songs", ["genre_id"], name: "index_genre_songs_on_genre_id", using: :btree
add_index "genre_songs", ["song_id"], name: "index_genre_songs_on_song_id", using: :btree
create_table "genres", force: true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "songs", force: true do |t|
t.string "title"
t.string "artist"
t.text "url"
t.string "track_file_name"
t.string "track_content_type"
t.integer "track_file_size"
t.datetime "track_updated_at"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "plusminus"
end
You need to get rid off gendre_name method, as it doesn't give you what you want. You've assigned #songs to some list of songs, hence most likely somewhere in your view you have sth like:
<% #songs.each do |song| %>
# display song row
<% end %>
if so, use sth like below inside this each "loop":
(<%= song.genres.map(&:names).join(', ') %>)
Related
In my ruby on rails application i've applied a relationship between two table: Article and Category with a relation has_and_belongs_to_many.
class Category < ActiveRecord::Base
has_and_belongs_to_many :articles
end
class Article < ActiveRecord::Base
has_and_belongs_to_many :categories
end
I'm following this tutorial for implement a Has_many system with the checkboxes (Railcast)
i've write this part:
<% for category in Category.all%>
<div>
<%= check_box_tag "article[category_ids][]", category.id, #article.categories.include?(category) %>
<%= category.name %>
</div>
<% end %>
but i've got this error :
Mysql2::Error: Table 'CMS_development.articles_categories' doesn't exist: SHOW FULL FIELDS FROM articles_categories
Where am i wrong?
EDIT ADDING THE MIGRATION AND THE SCHEMA
MIGRATION:
class AddCategoryToArticles < ActiveRecord::Migration
def change
add_reference :articles, :category, index: true, foreign_key: true
end
end
SCHEMA:
ActiveRecord::Schema.define(version: 20151001153131) do
create_table "articles", force: :cascade do |t|
t.boolean "published"
t.boolean "on_evidance"
t.boolean "foreground"
t.string "title", limit: 255
t.string "subtitle", limit: 255
t.datetime "date"
t.text "body", limit: 65535
t.text "small_body", limit: 65535
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "category_id", limit: 4
end
add_index "articles", ["category_id"], name: "index_articles_on_category_id", using: :btree
create_table "categories", force: :cascade do |t|
t.string "name", limit: 255
t.text "description", limit: 65535
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_foreign_key "articles", "categories"
end
Two issues:
You don't have the join table articles_categories
You're not referencing the categories correctly
Firstly, to use a has_and_belongs_to_many association, you need to invoke the appropriate join table:
Your schema shows, quite clearly, that you don't have this. As stated in other answers, you need to create a schema as follows:
class CreateArticlesCategories < ActiveRecord::Migration
def change
create_table :articles_categories, id: false do |t|
t.references :articles
t.references :categories
end
end
end
This will give you the join table which you'll be able to populate with your select box...
--
For your checkbox, you can do the following:
#app/views/articles/new.html.erb
<%= form_for #article do |f| %>
<%= f.collection_select :categories, Category.all, :id, :name %>
<%= f.submit %>
<% end %>
To populate this through the controller, you'd need to use the following:
#app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def new
#article = Article.new
end
def create
#article = Article.new article_params
#article.save
end
private
def article_params
params.require(:article).permit(:title, :categories)
end
end
You should write and execute a migration for creating articles_categories table:
class CreateArticleCategory < ActiveRecord::Migration
def change
create_table :articles_categories do |t|
t.references :articles
t.references :categories
end
end
end
What I'd like to do is to display the name in the details table.
I tried some codes, but I couldn't.
Please advise me on how to display the value.
Controller code:
class BooksController < ApplicationController
def show
#book = Book.find(params[:id])
#article = Article.where(book_id: (params[:id])).order(day: :asc)
end
end
View code:
<div class="row">
<% #article.each do |a| %>
<%= a.day %><br>
<%= a.title %><br>
# want to display the name in detail table where (details.day = articles.day and details.book_id = articles.book_id)
<% end %>
</div>
Relevant model setup:
class Article < ActiveRecord::Base
belongs_to :Book
default_scope -> { order(day: :asc, start_time: :asc) }
end
class Detail < ActiveRecord::Base
belongs_to :Book
end
class Book < ActiveRecord::Base
has_many :articles
has_many :details
end
Schema:
ActiveRecord::Schema.define(version: 2015099999999) do
create_table "details", force: true do |t|
t.integer "book_id"
t.integer "day"
t.string "name"
t.string "detail"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "articles", force: true do |t|
t.integer "book_id"
t.integer "day"
t.string "start_time"
t.string "end_time"
t.integer "category"
t.string "title"
t.string "contents"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "books", force: true do |t|
t.date "publish_date"
t.string "title"
t.datetime "created_at"
t.datetime "updated_at"
end
end
You want to define an association between Article and Detail using the :through option:
class Article < ActiveRecord::Base
belongs_to :book
has_many :details, through: :book
end
You can also define an accessor to find just the detail for the matching day:
class Article < ActiveRecord::Base
def matching_detail
details.find_by_day day
end
end
Which you can then use in the view:
<% #article.each do |a| %>
<%= a.matching_detail.try(:name) %>
<% end %>
It's good to define the associations for articles like
has_many :details, through: :book
You can also also use this .
Article.includes(:details).where(book_id: (params[:id])).order(day: :asc)
Or
Article.select('articles.name,details.name,..').joins(:details).where([condition])
So, I have 3 models Quotes, Categories, and Subscribers.
Essentially, it's a newsletter application. Subscribers can select a category and then enter their email and they will receive quotes related to that category via email.
There's two issues here,
1. The category's are stored in a constant in the category model.
so how do I display the category type that the subscriber chose
in text format? I'd like to show in the email
something like "here's your email on <%= category.name %>" which would translate to
"here's your email on Food."
2. I'd like to ONLY send emails about the category that the subscriber subscribed to.
How might I accomplish this? Please provide examples.
This is what I have so far:
Category.rb
class Category < ActiveRecord::Base
belongs_to :quote
belongs_to :subscriber
CATEGORY_TYPE = {
1 => "Food",
2 => "Fitness",
3 => 'Cats',
}
end
Quote.rb
class Quote < ActiveRecord::Base
has_many :categories
belongs_to :category
validates :title, presence: true
end
Subscriber.rb
class Subscriber < ActiveRecord::Base
has_one :category
validates :email, presence: true
end
schema
create_table "categories", force: true do |t|
t.string "name"
t.integer "quote_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "subscriber_id"
t.integer "category_type"
end
create_table "quotes", force: true do |t|
t.string "title"
t.text "body"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "subscribers", force: true do |t|
t.string "email"
t.datetime "created_at"
t.datetime "updated_at"
end
Update subscribers_mailer.rb
def SendMyEmail(email, category, quote, subscribers)
#category = category
#quote = quote
#subscribers = subscribers
#email = email
mail to: email, subject: 'New Quotes'
end
end
and then of course:
Category.all.each do |category|
SubscriptionMailer.SendMyEmail("email#test.com", category, category.quotes.first, category.subscribers).deliver
end
Update:
There's two remaining issues here,
1. Categories aren't syncing to subscribers. For example when I run category.subscribers.last
it's nil. and category.subscribers throws an empty array. How can I sync these? I think it has
to do with the fact that subscribers are selecting a category from the Category::CATEGORY_TYPES
constant as seen in the view code below.
2. I'd like to automate it so that these emails are sent to subscribers once a day.
How might I do this?
view code (subscribers/new.html.erb:
<div class="styled email-input2">
<%= form_for #subscriber do |f| %>
<% if #subscriber.errors.any? %>
<div class="errorExplanation" style="color: white;">
<h2><%= pluralize(#subscriber.errors.count, 'error') %> encountered:</h2>
<ul>
<% #subscriber.errors.full_messages.each do |m| %>
<li><%= m %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.fields_for :subscriber, #subscriber.build_category do |cat| %>
<%= cat.select(:category_type, Category::CATEGORY_TYPE.map{|p| [p[1], p[0]]}, {prompt: 'Please select'}, {class: 'styled email-input2'}) %>
<% end %>
</div>
Ok first lets modify the migrations:
create_table "categories", force: true do |t|
#DELETE QUOTE_ID AND SUBSCRIBER ID
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "category_type"
end
create_table "quotes", force: true do |t|
t.string "title"
t.text "body"
t.datetime "created_at"
t.datetime "updated_at"
t.references :category #this will add integer category_id
end
create_table "subscribers", force: true do |t|
t.string "email"
t.datetime "created_at"
t.datetime "updated_at"
t.references :category #this will add integer category_id
end
Next we will modify the models to reflet the changes in the migration:
class Category < ActiveRecord::Base
has_many :quotes
has_many :subscribers
CATEGORY_TYPE = {
1 => "Food",
2 => "Fitness",
3 => 'Cats',
}
end
class Quote < ActiveRecord::Base
belongs_to :category
validates :title, presence: true
end
class Subscriber < ActiveRecord::Base
belongs_to :category
validates :email, presence: true
end
Now you can get the subscribers for a cateogyr using the following:
category = Category.find(1) #use whatever id you want
category.subscribers #list of all subscribers for a category
Getting the quotes for a category is similarly straight forward:
category = Category.find(1)
category.quotes
So assuming your mailer takes a category, quote and a list of subscribers for the email to send
Category.all.each do |category|
Mailer.SendMyEmail(category, category.quotes.first, category.subscribers).deliver
end
In the "SendMyEmail" function in your mailer you will have
def SendMyEmail(category, quote, subscribers)
#YOUR CODE FOR TYHE VIEW HERE
end
I'm trying to set up a simple search from one view through a joined table and, being a newbie, it's not quite working. I'm testing with the word "books" which I know is in the articles table in the subject column.
My error is:
SQLite3::SQLException: no such column: articles.subject: SELECT COUNT(*) FROM "keywords" WHERE (articles.subject LIKE '%books%')
My schema is:
create_table "articles", force: true do |t|
t.string "title"
t.string "subject"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "articles_keywords", id: false, force: true do |t|
t.integer "article_id"
t.integer "keyword_id"
end
create_table "keywords", force: true do |t|
t.string "keyword"
t.datetime "created_at"
t.datetime "updated_at"
end
My model is:
class Keyword < ActiveRecord::Base
has_and_belongs_to_many :articles
accepts_nested_attributes_for :articles
def self.search_for(query)
where('articles.subject LIKE :query', :query => "%#{query}%")
end
My controller action is:
def index
#keywords = params[:q] ? Keyword.search_for(params[:q]) : Keyword.all
end
My view action is:
<%= form_tag "/", method: "GET" do %>
<%= text_field_tag :q %>
<%= submit_tag "Search" %>
<% end %>
<% if #keywords.any? %>
<% #keywords.each do |k| %>
<section>
<h3><b>Title</b>: <%= link_to k.keyword.title, keyword.title %></h3>
<p><b>Subject</b>: <%= keyword.subject%></p>
<% end %>
Many thanks for any help!
You have to join the asocciated table (and you can use scopes):
class Keyword < ActiveRecord::Base
has_and_belongs_to_many :articles
accepts_nested_attributes_for :articles
scope :search_for, ->(query){ joins(:acticles).where('articles.subject LIKE :query', :query => "%#{query}%")}
end
See RubyOnRails-Guides
A gem that eases complex querying is squeel. With squeel the scope would by
scope :search_for, ->(query){ joins{articles}.where{articles.subject =~ "%#{query}%"} }
I am now trying to show the images, which a user already registered, on his or her 'mypage'.
Then, I wrote some codes as below.But it doesn't work.Could you give me some advises?
☆members_controller
#member= Member.find(params[:id])
#member.groups.reverse.map do |group|
#join_groups_images = group.imageurl
☆(members)show.html.erb
<div class="join_groups_images">
<%= image_tag #join_groups_images, :width => '20px' ,:height => '25px' %>
</div>
☆(model)member.rb
class Member < ActiveRecord::Base
attr_accessible :admin, :mail, :memo, :name, :pass, :user, :pass_confirmation
has_many :group_in_members, :dependent => :destroy
has_many :groups, :through => :group_in_members
☆(model)group_in_member.rb
class GroupInMember < ActiveRecord::Base
attr_accessible :group_id, :member_id
belongs_to :group
belongs_to :member
end
☆schema.rb
create_table "groups", :force => true do |t|
t.string "name"
t.text "memo"
t.boolean "admin"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "imageurl"
end
You didn't provide whole code from action in members controller, but I assume, that you are using .map{|| } in wrong way. You need a variable with array or even method in Member model.
class Member < ActiveRecord::Base
...
def images
groups.reverse.map(&:imageurl)
end
...
end
and then, put this in your view
<ul class="join_groups_images">
<% #member.images.each do |image| >
<li><%= image_tag image %></li>
<% end>
</div>
that should do the trick.