Find or Initialize By Parameter Confusion Rails 4 - ruby-on-rails-4

I'm trying to use 'find_or_initialize_by' in my orders controller. I need to find the record by two parameters, user_id and item_id. If that particular order combination doesn't exist then I would like to create it.
Here is what I have in the orders controller:
def create
#order = Order.find_or_initialize_by(#not sure of syntax here)
#order.update_attributes(quantity_requested)
#order.save
redirect_to :back
end
I've tried many different parameters and all produce error messages. Can anyone please clarify the correct way to pass parameters here?
Thank you for any and all help.
Edit to add more code:
db schema:
create_table "orders", force: true do |t|
t.integer "item_id"
t.integer "quantity_requested"
t.boolean "order_completed"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
Order model:
class Order < ActiveRecord::Base
belongs_to :user
has_one :item, dependent: :destroy
validates :user_id, presence: true
end
Item show:
<%= form_for Order.new do |f| %>
<%= f.number_field :quantity_requested, value: 0, max: #item.quantity, min: 1, class: "item-quantity form-control", :onclick => '$(this.form).submit()' %>
<% end %>

find_or_initialize_by takes two parameters. The first is a hash, and the second is a block to be used if nothing is found and is instead initialized. If you don't need the block, you can just do:
#order = Order.find_or_initialize_by(user_id: value, item_id: value)

Related

Simple_form Nested attribute in Rails 4

It's been a week and I'm still stuck trying to create a new form that updates my associated model. I have read so many post with a similar problem and is killing me inside.
The same old Gallery has_many :photosand Photo belongs_to :gallery
I have already nested my resources. When I submit my form I also get a routing error.
resources :galleries do
resources :photos do
end
end
Already included accepted_nested_attribute_for :photos in my :gallery model
How should I write my new and create method for my photos controller? Should I use .build instead of .create, should I use fields_for instead of form_for? I notice rails 4 is using strong params, so do I need to permit gallery inside my photos controller.
Sorry guys I read, and watched so many videos and even though I copy code for code still stuck.
My simple_form keeps on getting all sorts of error:
<%= simple_form_for :photos, html:{multipart: true} do |f| %>
<%= f.input :position, collection: 1..10 %>
<%= f.input :publish %>
<%= f.input :caption, placeholder:"Please insert caption here", label:false %>
<%= f.input :image, label:false %>
<%= hidden_field_tag 'user_id', current_user.id %>
<%= hidden_field_tag 'gallery_id', gallery.id %>
<%= f.button :submit %>
<% end %>
My goal is to pass on my gallery's id to my photos. This is my scheme:
create_table "photos", force: :cascade do |t|
t.text "caption"
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"
t.integer "gallery_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "position"
t.boolean "publish"
end
create_table "galleries", force: :cascade do |t|
t.string "title"
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"
t.integer "user_id"
t.string "tag"
t.boolean "publish"
end
So you have a gallery form for inserting multiple pictures inside your gallery, you need to get the gallery from the params.
Firstly in your photos_controller.rb
def new
#gallery = Gallery.find(params[:gallery_id)
#gallery.photos.build
end
and your form, you should use cocoon or nested_form_fields(my preferred choice)
simple_form_for #gallery do |f|
f.simple_fields_for :pictures do |p|
p.input :title
p.input :your_other_stuff
whitelist the params by doing
def params
params.require(:gallery).permit(:gallery, :stuff, :in_here, pictures: [:pictures, :stuff, :in_here])
end

Can't get has_many & belongs_to in same model to work

It has been a while since I asked something around here.
Since I have just started playing around with Ruby, and can't get my head around this, I decided to come back here for some guidance.
I've read quite a few examples now, but I don't find a proper path to walk to solve this problem.
The idea is the following :
You have :
A family
A person
Their relationship is the following :
There is one person that is the 'head' of the family
Every person is part of a family (be it with multiple persons or just himself in it)
Now the current validation probably makes it impossible to perform this, but the idea is that there is no such thing as a family without a head, and no person without a family.
I've tried to express it the following way :
Family class
class Family < ActiveRecord::Base
validates :head_id, presence: true
belongs_to :head, :class_name => Person, foreign_key: 'head_id'
has_many :persons
end
Person class
class Person < ActiveRecord::Base
validates :family_id, presence: true
validates :first_name, presence: true
belongs_to :family
end
Would any soul be so kind to offer me some advice?
The migration has a family_id on the Person-class side, the family consists of an extra column being person_id.
Family migration
class CreateFamilies < ActiveRecord::Migration
def change
create_table :families do |t|
t.integer :head_id
t.timestamps null: false
end
end
end
Person migration
class CreatePersons < ActiveRecord::Migration
def change
create_table :persons do |t|
t.string :first_name
t.string :last_name
t.integer :age
t.integer :family_id
t.timestamps null: false
end
end
end
You got a circular dependency here. You cannot create families nor people.
Circular dependency usually indicates that there's a third element missing.
More eloquently and not completely related .
There are two kind of membership, head and non-head. Once your make them obvious in your code the circular dependency will be solved.
There a few solutions but you need to find the one fits you the best. This is mine.
Create a membership join table
class Family
validates :memberships, presence: true, on: :update
has_many :memberships
has_many :people, through: :membership
after_create :create_head_membership
private
def create_head_membership
memberships.create role: 'head' # to be filled later
end
end
class Membership
belongs_to :family
belongs_to :person
end
class Person
has_many :memberships
has_one :family, through: :membership # has_many, amrite?
validates :memberships, presence: true, on: :update
end
The most important thing is avoid Person/Family direct manipulation, rather create something to handle this process and wrap it in a transaction
class God
def make_family head_attrs
fam, head = nil
Family.transaction do
fam = Family.create!
head = Person.create! head_attrs
fam.memberships.first.update_attribute! :person_id, head.id
end
fam
end
end
I am not sure if I properly understand your code, but please tell me what is a Publisher class? I think you should do it in this way:
Family model:
has_many :persons
has_one :head, :class_name => Person, foreign_key: 'head_id'
validates :head_id, presence: true
Person model:
belongs_to :family
validates :family_id, presence: true
validates :first_name, presence: true
Family has many persons and has one head. The person belongs to family and it doesn't matter for the person if it's the head of family or not.
Other things like migrations and validations still the same.
Is better validate presence of :head that not head_id
class Family < ActiveRecord::Base
validates :head, presence: true
belongs_to :head, :class_name => Person, foreign_key: 'head_id'
has_many :persons
end
Person have two relations with Family, one if is head and another if is part of a family, you have to validate (as I put in the example) how you can handle this relationships.
class Person < ActiveRecord::Base
validates :family, presence: true
validates :first_name, presence: true
belongs_to :family
belongs_to :head, :class_name => 'Family', :foreign_key => 'head_id'
validate :family_id_is_equal_to_head_id
def family_id_is_equal_to_head_id
self.family = self.head
end
end
Finally migrations are wrong, must define the relantionship
class CreateFamilies < ActiveRecord::Migration
def change
create_table :families do |t|
t.integer :head_id
t.timestamps null: false
end
end
end
class CreatePersons < ActiveRecord::Migration
def change
create_table :persons do |t|
t.string :first_name
t.string :last_name
t.integer :age
t.belongs_to :family
t.integer :head_family_id
t.timestamps null: false
end
end
end

fields_for a nested resource not working

I have the following associations:
class Campaign < ActiveRecord::Base
has_many :events
end
class Event < ActiveRecord::Base
belongs_to :campaign
belongs_to :venue
accepts_nested_attributes_for :venue
end
class Venue < ActiveRecord::Base
has_many :events
end
And I have the following form:
<%= form_for([#campaign, #event]) do |f| %>
<%= f.fields_for :venue do |v| %>
<%= v.text_field :search %>
<% end %>
<% end %>
Anything in the fields_for block is not showing up. But the funny thing is if i change f.fields_for :venue to f.fields_for :venues, the :search field shows up.
But :venues shouldn't be plural on :events. Even in rails console Event.venues does not work
NoMethodError: undefined method `venues'
It also generates the wrong field names
This makes me think I have my model associations jacked up, but after reviewing the docs. it does not seem so. Here is my schema for reference:
create_table "campaigns", force: true do |t|
t.integer "user_id"
t.string "title"
t.text "description"
t.integer "image_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "events", force: true do |t|
t.integer "campaign_id"
t.datetime "start_date"
t.datetime "end_date"
t.integer "venue_id"
t.integer "image_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "title"
t.text "description"
end
create_table "venues", force: true do |t|
t.float "latitude"
t.float "longitude"
t.string "address1"
t.string "address2"
t.string "city"
t.string "zip"
t.string "state"
t.string "country"
t.string "name"
t.string "gid"
t.datetime "created_at"
t.datetime "updated_at"
end
See the similar SO Posts
1.Does accepts_nested_attributes_for work with belongs_to?
2.Getting fields_for and accepts_nested_attributes_for to work with a belongs_to relationship
As mentioned in one of those posts,one way of achieving it is changing the accepts_nested_attributes_for to the has_many side
class Campaign < ActiveRecord::Base
has_many :events
accepts_nested_attributes_for :events
end
class Event < ActiveRecord::Base
belongs_to :campaign
belongs_to :venue
end
class Venue < ActiveRecord::Base
has_many :events
accepts_nested_attributes_for :events
end
If it is not,you might want to build a venue for events with #event.build_venue in the controller before calling fields_for.
Hope it helps!

Displaying many-to-many using select multiple

right now im building a form that accepts a many to many using a select multiple. after creating the form, im trying to display the information collected in the SHOW page however i dont know how to display that data in embedded ruby. join model is CardTypesList
Models
class Card < ActiveRecord::Base
self.inheritance_column = nil
validates :name, presence: true, uniqueness: {case_sensitive: false}
has_many :card_type_lists
has_many :card_types, through: :card_type_lists
accepts_nested_attributes_for :card_type_lists
end
class CardType < ActiveRecord::Base
has_many :card_type_lists
has_many :cards, through: :card_type_lists
end
class CardTypeList < ActiveRecord::Base
belongs_to :cards
belongs_to :card_types
accepts_nested_attributes_for :card_type
end
NEW form using select
<%= f.label :types %>
<%= f.select :card_type_ids, CardTypes.all.collect{|x| [x.name, x.name]}, {},{:title => "Select a Type", :multiple => true, :class => 'selList'} %>
Embedded ruby trials
<td class="card-td"><%= #card.card_types %></td>
Expected: ["Type 1", "Type2"]
this renders the page, but yields (in text):
<ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_CardTypes:0x00000102f58a18>
EDIT: schema added.
ActiveRecord::Schema.define(version: 20140120042152) do
create_table "card_type_lists", force: true do |t|
t.integer "card_type_id"
t.integer "card_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "card_types", force: true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "cards", force: true do |t|
t.string "name"
t.string "set"
t.string "card_types"
t.string "colors"
t.string "cost"
t.string "rarity"
t.string "oracle"
t.float "value"
t.integer "number_owned"
t.string "notes"
t.string "img_link"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "types_mask"
end
add_index "cards", ["name"], name: "index_cards_on_name", unique: true
end
and this is my controller:
class CardsController < ApplicationController
def new
#card = Card.new
#card.card_type_lists.build.build_card_type
end
def show
#card = Card.find(params[:id])
end
def create
#card = Card.new(card_params)
if #card.save
redirect_to #card
else
render 'new'
end
end
private
def card_params
params.require(:card).permit(:name, :set, {:card_types => []}, :color, :cost, :rarity,:oracle,:value, :number_owned,:notes)
end
end
Should be:
class CardTypeList < ActiveRecord::Base
belongs_to :card
belongs_to :card_type #Singular
end
Some more things to think about:
Does your join model have the correct columns?
You should use accepts_nested_attributes_for
Look at how you're calling the data
Schema
Join models in has_many :through have to have foreign_key references to both models they're joining. The way you do this is to use a schema like this:
card_types_lists
id | card_id | card_type_id | other | information | created_at | updated_at
When you mentioned the error no such column: card_type_lists.card_types_id, it generally means you either don't have the correct column in the db, or your reference is incorrect. Looking at it, it's your association (referencing plural instead of singular)(fixed above)
Forms
Something you should consider is using accepts_nested_attributes_for to send the correct data to the nested models
This is when you want to create some records in either model, and works by allowing you to define "new" objects for your other models in your parent model, passing the data to your child models, like this:
#app/models/card.rb
Class Card < ActiveRecord::Base
has_many :card_type_lists
has_many :card_types, through: :card_type_lists
accepts_nested_attributes_for :card_type_lists
end
#app/models/card_type_list.rb
Class CardTypeList < ActiveRecord::Base
belongs_to :card
belongs_to :card_type
accepts_nested_attributes_for :card_type
end
#app/controllers/cards_controller.rb
def new
#card = Card.new
#card.card_types_lists.build.build_card_type
end
Data
If you want to show your associative data correctly, you should try this:
#app/views/cards/show.html.erb
<%= #card.card_types %>

Rails Simple_Form Association Not Working

New to RoR. I am making a simple blog to post music entries. I have two models Tune and Artist where a tune belongs_to an artist. I am using simple_form to render my form. The problem I am running into is that the simple_form is pulling up the correct associations but when I click submit it is not saving the association correctly and the validation isn't passing. Code is below:
Classes
class Tune < ActiveRecord::Base
belongs_to :artist
validates :artist, presence: true
end
class Artist < ActiveRecord::Base
has_many :tunes
end
Database schema
ActiveRecord::Schema.define(version: 20131027190309) do
create_table "artists", force: true do |t|
t.string "name"
t.string "real_name"
t.string "gender"
t.string "city"
t.string "country"
t.string "artist_soundcloud_link"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "tunes", force: true do |t|
t.string "soundcloud_link"
t.string "download_link"
t.string "download_label"
t.string "name"
t.string "style"
t.boolean "mix"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "artist_id"
end
add_index "tunes", ["artist_id"], name: "index_tunes_on_artist_id"
end
My form
<%= simple_form_for #tune, :html => { :class => 'form-horizontal' } do |f| %>
<%= f.input :name %>
<%= f.input :soundcloud_link %>
<%= f.input :download_label %>
<%= f.input :download_link %>
<%= f.input :mix %>
<%= f.association :artist%>
<%= f.button :submit %>
<% end %>
Add following to your Tune model
accepts_nested_attributes_for :tunes
and then add strong params to your controller, e.g.
params.require(:artist).permit( :id, :name, ... , tune_attributes: [:id, :name, :real_name, ...] )
NOTE: I am assuming your are using rails 4