belongs_to add a relationship? - ruby-on-rails

these are my models
class Apartment
belongs_to :house
end
class House
has_many :apartments
end
apartment_controller;
def index
#apartments = Appartment.all
end
apartment index view
.span9
#container
- #appartments.each do |apartment|
.item{:class => apartment.features_to_html_class }
%article.info.t_xs
.article-base
%section
.span3
%h2 #{link_to apartment.name, appartment_path(apartment)}
%p
= raw truncate(apartment.property_description, :length => 375, :omission => '...')
%footer
%ul.meta
%li.comments
#{apartment.count_ratings}
= t('apartment.details.reviews')
%li.notes
#{apartment.guests}
= t('apartment.details.persons')
%li.notes
#{apartment.bedrooms}
= t('apartment.details.bedrooms')
%li.notes
#{apartment.bathrooms}
= t('apartment.details.bathrooms')
%ul.thumbnails
%li.span5
= image_tag(apartment.attachments.last.file.url, :class => 'thumbnail')
- apartment.attachments.limit(4).each do |a|
%li.span1
%a{:href => "#"}
= image_tag(a.file.url(:thumb), :class => "thumbnail")
.span8
%footer
#more
#{link_to t('apartments.summary.button'), appartment_path(apartment), :class => 'btn btn-primary'}
i get all the apartments from the DB. But now i want to add a link (belongs_to) to the house in at the apartment summary. how can i do this...thanks..remco

Did you try
link_to 'House', house_path(apartment.house) ?

Try this:
<%= link_to 'House', house_path(apartment.house) %>
or
<%= link_to 'House', house_url(apartment.house) %>
Regards!

You got all the apartments in the database.
Now you run the sql to get the apartments object.
Then iterate each apartment and link it to house with the association.
This is done as follows:
def index
#apartments = Appartment.all
#apartments.each do |apartment|
#this is giving you the link to house via association defined.
apartment.house
#this is giving you the value of the field say `house_name` of house table that is linked to apartment.
#house_name = apartment.house.house_name
.
.
.
end
end

Related

For each loop through API values

I'm having trouble finding the correct way to list out all of my data here is my setup. #product.pic_url will return 5 images but only shows the first one how would I iterate through them all?
product.rb
class TaobaoProduct
attr_reader :desc,
:approve_status,
:title,
:item_url,
:nick,
:num_iid,
:pict_url,
:pic_url,
:title,
:volume,
:zk_final_price,
:reserve_price,
:price,
:detail_url,
:cid
attr_writer :title
def initialize(product)
product.each { |name, value| instance_variable_set("##{name}", value) }
end
# function to get individual taobao product
# product_id: Taobao product id
def self.find(product_id)
tb_hash = OpenTaobao.get(
:method => 'taobao.item.get',
:fields => 'num_iid,title,nick,desc,pic_url',
:num_iid => product_id
)
new(tb_hash["item_get_response"]["item"])
end
end
product.haml
.container
.row
.col-xs-12
%h1= #product.title
.row
.product-v2.col-md-9
.row
.col-md-6.col-xs-12
%img{:src => "#{#product.pic_url}" + "_400x400.jpg"}
.col-md-6.col-xs-12
.price-v2
Assuming Product#pic_url actually returns an array of image urls, you could do something like this:
.container
.row
.col-xs-12
%h1= #product.title
.row
.product-v2.col-md-9
.row
.col-md-6.col-xs-12
- #product.pic_url.each do |url|
%img{:src => "#{url}_400x400.jpg"}
.col-md-6.col-xs-12
.price-v2

Rails4 advice: How should I create multiple records in a model from single view?

Been struggling with this query for a few days. I have 3 models Books, Children and Hires. I have created a view for hires which allows a user to select 2 books and a single child and what i'm looking to do is insert two rows to reflect this into the 'hires' table. I have some JS that populates the hidden fields with the values that they require. Now, I don't think nested attributes is the way to go, because i'm trying to insert directly into the joining table.
So, what i'm trying now is the following:
hires/_form.html.erb
<%= form_for(#hire) do |f| %>
<% 2.times do %>
<%= f.hidden_field :child_id %>
<%= f.hidden_field :book_id %>
<% end %>
<%= f.submit 'Take me home' %>
<% end %>
and then what I want to do is to run through the 'create' function twice in my controller and thus create two rows in the 'hires' model. Something like this:
hires_controller.rb
def create
hire_params.each do |hire_params|
#hire = Hire.new(hire_params)
end
end
Is this completely the wrong way to go? I'm looking for advice on the right way to do this? If this will work, what's the best way to format the create statement?
** Edit **
I have 3 models. Each Child can have 2 books. These are my associations:
class Child < ActiveRecord::Base
has_many :hires
has_many :books, through: :hires
end
class Hire < ActiveRecord::Base
belongs_to :book
belongs_to :child
accepts_nested_attributes_for :book
accepts_nested_attributes_for :child
end
class Book < ActiveRecord::Base
has_many :hires
has_many :children, through: :hires
belongs_to :genres
end
hires/new.html.erb
<div class="form-inline">
<div class="form-group">
<h1><label for="genre_genre_id">Pick Book 1:
<%=collection_select(:genre1, :genre_id, #genres.all, :id, :Name, {prompt: true}, {:class => "form-control dropdown"})%></label></h1>
</div>
</div>
<div id="book1-carousel" class="owl-carousel owl-theme">
<% #books.each do |book| %>
<div data-id = "<%= book.id %>" class="tapbook1 tiles <% #genres.each do |g|%> <% if g.id == book.Genre_id %> book1genre<%=g.id %> <% end end%> <%= %>"><a class="item link"><% if book.bookimg.exists? %><%= image_tag book.bookimg.url(:small), :class => "lazyOwl", :data => { :src => book.bookimg.url(:small)}%> <%end%></br><p class="tile_title" ><%= book.Title %></p></a></div>
<% end %>
</div>
<div class="form-inline">
<div class="form-group">
<h1><label for="genre_genre_id">Pick Book 2:
<%=collection_select(:genre2, :genre_id, #genres.all, :Name, :Name, {prompt: true}, {:class => "form-control dropdown"})%></label></h1>
</div>
</div>
<div id="book2-carousel" class="owl-carousel owl-theme">
<% #books.each do |book| %>
<div data-id = "<%= book.id %>" id="<%= book.id %>" class="tapbook2 tiles <% #genres.each do |g|%> <% if g.id == book.Genre_id %> book2genre<%=g.id %> <% end end%> <%= %>"><a class="item link"><% if book.bookimg.exists? %><%= image_tag book.bookimg.url(:small) , :class => "lazyOwl", :data => { :src => book.bookimg.url(:small)}%> <%end%></br> <p class="tile_title"><%= book.Title %></p></a></div>
<% end %>
</div>
<h1 class="child_heading1" >Now choose your name:</h1>
<div id="children-carousel" class="owl-carousel owl-theme">
<% #children.each do |child| %>
<div data-id = "<%= child.id %>" class="tapchild tiles"><a class="item link"><% if child.childimg.exists? %><%= image_tag child.childimg.url(:small), :class => "lazyOwl", :data => { :src => child.childimg.url(:small)} %> <%end%></br> <p class="tile_title"><%= child.nickname %></p></a></div>
<% end %>
</div>
<%= render 'form' %>
and the coffeescript:
hires.coffee
$(document).on 'ready page:load', ->
book1carousel = $("#book1-carousel")
book2carousel = $('#book2-carousel')
book1carousel.owlCarousel items: 5, lazyLoad : true
book2carousel .owlCarousel items: 5, lazyLoad : true
$('#children-carousel').owlCarousel items: 5, lazyLoad : true
book1clickcounter = 0
book2clickcounter = 0
childclickcounter = 0
book1selection = 0
book2selection = 0
$('.tapbook1').on 'click', (event) ->
$this = $(this)
book1id = $this.data('id')
book1selection = book1id
if $this.hasClass('bookclicked')
$this.removeAttr('style').removeClass 'bookclicked'
book1clickcounter = 0
$('#hire_book_id').val("");
book1selection = 0
else if book1clickcounter == 1
alert 'Choose one book from this row'
else if book1selection == book2selection
alert "You've already picked this book"
else
$('#hire_book_id').val(book1id);
$this.css('border-color', 'blue').addClass 'bookclicked'
book1clickcounter = 1
return
$('.tapbook2').on 'click', (event) ->
$this = $(this)
book2id = $this.data('id')
book2selection = book2id
if $this.hasClass('book2clicked')
$this.removeAttr('style').removeClass 'book2clicked'
book2clickcounter = 0
book1selection = 0
else if book2clickcounter == 1
alert 'Choose one book from this row'
else if book1selection == book2selection
alert "You've already picked this book"
else
$this.css('border-color', 'blue').addClass 'book2clicked'
book2clickcounter = 1
return
$('.tapchild').on 'click', (event) ->
$this = $(this)
childid = $this.data('id')
if $this.hasClass('childclicked')
$this.removeAttr('style').removeClass 'childclicked'
childclickcounter = 0
$('#hire_child_id').val("");
else if childclickcounter == 1
alert 'Choose one child from this row'
else
$this.css('border-color', 'blue').addClass 'childclicked'
childclickcounter = 1
$('#hire_child_id').val(childid);
return
jQuery ($) ->
$('td[data-link]').click ->
window.location = #dataset.link
return
return
return
My approach to this would be what's called a form object, a class that acts like a model but exists only to handle the creation of multiple objects. It provides granular control, but at the expense of duplicating validations. In my opinion (and that of many others), it's a much better option than nested attributes in most cases.
Here's an example. Note that I don't have any idea what your application does, and I didn't look at your associations close enough to make them accurate in this example. Hopefully you'll get the general idea:
class HireWithBookAndChild
include ActiveModel::Model
attr_accessor :child_1_id, :child_2_id, :book_id
validates :child_1_id, presence: true
validates :child_2_id, presence: true
validates :book_id, presence: true
def save
if valid?
#hire = Hire.new(hire_params)
#child_1 = #hire.child.create(id: params[:child_1_id])
#child_2 = #hire.child.create(id: params[:child_2_id])
#book = #hire.book.create(id: params[:book_id])
end
end
end
By including AR::Model, you get validations and an object you can create a form with. You can even go into your i18n file and configure the validation errors messages for this object. Like an ActiveRecord model, the save method is automatically wrapped in a transaction so you won't have orphaned objects if one of them fails to persist.
Your controller will look like this:
class HireWithBookAndChildController < ApplicationController
def new
#hire = HireWithBookAndChild.new
end
def create
#hire = HireWithBookAndChild.new(form_params)
if #hire.save
flash['success'] = "Yay"
redirect_to somewhere
else
render 'new'
end
end
private
def form_params
params.require(:hire_with_book_and_child).permit(:child_1_id, :child_2_id, :book_id)
end
end
Your form will look like this:
form_for #hire do |f|
f.hidden_field :child_1_id
...
f.submit
end
You'll notice right away that everything is flat, and you aren't having to mess with fields_for and nested nested parameters like this:
params[:child][:id]
You'll find that form objects make your code much easier to understand. If you have different combinations of children, books and hires that you need to create, just make a custom form object for each one.
Update
A solution that might be more simple in this case is to extract a service object:
class TwoHiresWithChildAndBook < Struct.new(:hire_params)
def generate
2.times do
Hire.create!(hire_params)
end
end
end
And from your controller:
class HiresController
def create
generator = HireWitHChildAndBook.new(hire_params)
if generator.generate
*some behavior*
else
render :new
end
end
end
This encapulates the knowledge of how to create a hire in one place. There's more detail in my answer here: Rails 4 Create Associated Object on Save

Can't display my category and subcategory in the views Rails 4

My website has Categories and subcategories,here is what i have in my seeds.rb,there i create a main category called "Video and animation",and 4 subcategories,than i assign the subcategories to the main category.
#category = Category.create!(name: "Video and animation")
["Intro", "Animation & 3D", "Editing and Post Production", "Other"].each do |name|
#subcategory = Subcategory.create!(name: name, category_id: #category.id)
end
It works well,in my rails console i see that everything works,the category_id for the added products changes to a number(integer as it should).
Question: How do i show the category in my views,so when someone clicks on that he gets all the products of that category.
And how do i show all the subcategories following the same principle.
Here is what i tried to put into my views
<% Category.all.each do |category| %>
<%= link_to category.name, gigs_path(category: category.name) %>
<% end %>
<% Subcategory.all.each do |subcategory| %>
<%= link_to subcategory.name, gigs_path(subcategory: subcategory.name) %>
<% end %>
The weird thing is that when i put in my product controller
this
def index
#category_id = Category.find_by(name: params[:category])
#gigs = Gig.where(category_id: #category_id).order("created_at DESC")
#subcategory_id = Subcategory.find_by(name: params[:subcategory])
#gigs = Gig.where(subcategory_id: #subcategory_id).order("created_at DESC")
end
It shows just the required subcategories,as i want,but the main category remains empty.
and if i put instead this into my controller
def index
#category_id = Category.find_by(name: params[:category])
#subcategory_id = Subcategory.find_by(name: params[:subcategory])
#gigs = Gig.where(category_id: #category_id).order("created_at DESC")
end
The main category works,as required,but the subcategories remain empty.
Note: In both cases,in the views,before anyone clicks on anything,i see the proper category and subcategories displayed.
Here is what i have in each of the 3 models
class Category < ActiveRecord::Base
has_many :subcategories
end
class Subcategory < ActiveRecord::Base
belongs_to :category
has_many :products
end
class Product < ActiveRecord::Base
acts_as_votable
belongs_to :user
belongs_to :subcategory
has_attached_file :image, :styles => { :medium => "300x300>" }
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
end
Thank you for your time.
In controller action
#categories = Category.includes(:subcategories)
Add In views
<% #categories.each do |category| %>
<%= link_to category.name, gigs_path(category: category.name) %>
<% category.subcategories.each do |subcategory| %>
<%= link_to subcategory.name, gigs_path(subcategory: subcategory.name) %>
<% end %>
<% end %>
Change your index method in controller
def index
if params[:category]
c_id = Category.find(name: params[:category])
#gigs = Gig.where(category_id: c_id).order("created_at DESC")
elsif params[:subcategory]
subc_id = Subcategory.find(name: params[:subcategory])
#gigs = Gig.where(subcategory_id: subc_id).order("created_at DESC")
end
end

How to add a field into a snippet in Comfortable Mexican Sofa

I plan to use snippets in Comfortable Mexican Sofa to store email templates. But is there a way to add a field into a snippet. I would use it to store the subject of the email. Would be good to have also the subject in the cms so that our editors can change it if they feel like it.
By default snippets seem to have only two fields 'Label' and 'Identifier'. And of course the 'Content'. I would like to add also a 'Subject' String into the fields.
Simple Three Step Process:
1:
rails g migration AddSubjectToComfyCmsSnippets subject:string
2:
rake db:migrate
3:
create app/views/comfy/admin/cms/snippets/_form.html.haml with the following content:
- content_for :right_column do
= render 'comfy/admin/cms/files/index'
= render :partial => 'comfy/admin/cms/partials/snippet_form_before', :object => form
= form.text_field :label, :data => {:slugify => #snippet.new_record?}
= form.text_field :identifier, :data => {:slug => true}
= form.text_field :subject
= form.text_area :content, :data => {'cms-rich-text' => true}
= render :partial => 'comfy/admin/cms/categories/form', :object => form
= render :partial => 'comfy/admin/cms/partials/snippet_form_after', :object => form
= form.form_group :class => 'form-actions' do
= form.submit t(#snippet.new_record?? '.create' : '.update'), :class => 'btn btn-primary'
= link_to t('.cancel'), comfy_admin_cms_site_snippets_path, :class => 'btn btn-link'
Now you can reference the subject in your app like so:
Subject: #{#snippet.subject}
Monkey patch to get fixtures working:
create config/initializers/cms_monkey_patch.rb with the following contents:
ComfortableMexicanSofa::Fixture::Snippet::Importer.class_eval do
def import!
Dir["#{self.path}*/"].each do |path|
identifier = path.split('/').last
snippet = self.site.snippets.find_or_initialize_by(:identifier => identifier)
# setting attributes
categories = []
if File.exists?(attrs_path = File.join(path, 'attributes.yml'))
if fresh_fixture?(snippet, attrs_path)
attrs = get_attributes(attrs_path)
snippet.label = attrs['label']
snippet.subject = attrs['subject']
categories = attrs['categories']
end
end
# setting content
%w(html haml).each do |extension|
if File.exists?(content_path = File.join(path, "content.#{extension}"))
if fresh_fixture?(snippet, content_path)
snippet.content = extension == "html" ?
::File.open(content_path).read :
Haml::Engine.new(::File.open(content_path).read).render.rstrip
end
end
end
# saving
if snippet.changed? || self.force_import
if snippet.save
save_categorizations!(snippet, categories)
ComfortableMexicanSofa.logger.info("[FIXTURES] Imported Snippet \t #{snippet.identifier}")
else
ComfortableMexicanSofa.logger.warn("[FIXTURES] Failed to import Snippet \n#{snippet.errors.inspect}")
end
end
self.fixture_ids << snippet.id
end
# cleaning up
self.site.snippets.where('id NOT IN (?)', fixture_ids).each{ |s| s.destroy }
end
end
end
ComfortableMexicanSofa::Fixture::Snippet::Exporter.class_eval do
def export!
prepare_folder!(self.path)
self.site.snippets.each do |snippet|
snippet_path = File.join(self.path, snippet.identifier)
FileUtils.mkdir_p(snippet_path)
# writing attributes
open(File.join(snippet_path, 'attributes.yml'), 'w') do |f|
f.write({
'label' => snippet.label,
'subject' => snippet.subject,
'categories' => snippet.categories.map{|c| c.label}
}.to_yaml)
end
# writing content
open(File.join(snippet_path, 'content.html'), 'w') do |f|
f.write(snippet.content)
end
ComfortableMexicanSofa.logger.info("[FIXTURES] Exported Snippet \t #{snippet.identifier}")
end
end
end

This is getting printed in my views: #<Recipe:0x10536ff28>

Why am I seeing an activerecord object IDs for each record coming out of my Recipe model in my recipes views? At the bottom of the index action I see this:
#<Recipe:0x1056c1d98>#<Recipe:0x1056c1cd0>
The model:
class Recipe < ActiveRecord::Base
attr_accessible :name, :description, :quick_facts, :ingredients, :instructions, :user_id, :hashtag, :image
mount_uploader :image, ImageUploader
end
The view:
.section-header The Recipes as seen on: #DriscollsMoments
= recipes.each do |recipe|
#recipe
#image-container
= link_to(image_tag(recipe.image_url, :width => 200, :height => 100, :border => 0), recipe_path(recipe.id))
#information
= link_to recipe.name, recipe_path(recipe.id), :class => 'recipe-name'
= link_to 'view recipe & tweet', recipe_path(recipe.id), :class => 'view-recipe'
.clear
%p= recipe.description
.clear
The Controller:
class RecipesController < ApplicationController
def index
#recipes = Recipe.find(:all)
end
def show
end
end
This problem is unique to this model - it's not doing it anywhere else in my app. I tried disabling carrierwave to see if that had any affect and it doesn't appear to make any difference. I have two recipes_controllers, one's an admin controller, but that shouldn't be the problem either. I know this is going to be obvious. Any ideas?
In your view, replace this:
= recipes.each do |recipe|
with this:
- recipes.each do |recipe|
The = causes the contents of the recipes array to be output after executing the loop.
I believe the line:
= recipes.each do |recipe|
should be:
- recipes.each do |recipe|

Resources