Here is my newbie story,
my table looks like this:
create_table "books", :force => true do |t|
t.string "title"
t.integer "count"
t.integer "id"
end
create_table "users", :force => true do |t|
t.string "name"
t.decimal "money"
end
user can create many books, and user using these forms to update it:
to update money:
<%= form_for(#user) do |f| %>
<%= f.number_field :money, :value => #user.money %>
<% end %>
to update book title, count etc., for each books:
<% #book.each do |book| %>
<%= form_for(book) do |f| %>
<%= f.number_field :count %>
<%= f.text_field :title %>
<% end %>
<% end %>
and im trying to do is i want update both of them. (lets say user need to update money and book title) currently it only able to update money or book info separately
model:
class Book < ActiveRecord::Base
attr_accessible :count, :title, :id
belongs_to :user
end
any idea? Thanks!
It's not that simple to explain in a single answer. I suggest you to have a look at the following Railscasts to get an idea.
http://railscasts.com/episodes/198-edit-multiple-individually
http://railscasts.com/episodes/165-edit-multiple-revised
Related
UPDATE: Problem solved, thanks to Sebastian and Gabriel for the helpful pointers.
The relevant changes to my code are as follows:
app/controllers/pomodoro_cycles_controller.rb
def pomodoro_collections
{
pomodoro_collection_0: Pomodoro.offset(0).first(100),
pomodoro_collection_1: Pomodoro.offset(100).first(100)
}
end
app/views/pomodoro_cycles/show.html.erb
<% #pomodoros_collections.each do |pomodoros_collection_hash| %>
<h2><%= pomodoros_collection_hash[0] %></h2>
<% pomodoros_collection_hash[1].each do |pomodoro| %>
<p>
<%= pomodoro.id %>
<%= pomodoro.color %>
</p>
<% end %>
<% end %>
NOTA BENE:
The #first method in ActiveRecord returns an Array, so the keys in my original Hash were nested Arrays. Instead, the following was sufficient to return an Array of Pomodoro objects:
Pomodoro.offset(0).first(100)
DESCRIPTION OF ORIGINAL PROBLEM
Rails 5, PostgreSQL
PROBLEM: I cannot access Pomodoro.all from within PomodoroCycleController
I have two scaffolds: Pomodoro and PomodoroCycle, and I want to access the full list of Pomodoros within the PomdoroCycle controller.
The following code is kept simple, in order to make as clear as possible what I'm trying to do. If I can do these things, then I'll be able to do much more, but one step at a time.
Regarding the db migration files, I have already run bundle exec rails db:migrate
I want to display a full list of Pomodoros in the PomodoroCycle Show View (later to be displayed in Index), but I don't know what is missing.
From app/controllers/pomodoro_cycles_controller.rb
def show
#pomodoros_collections = pomodoro_collections
end
def pomodoro_collections
{
pomodoro_collection_0 => [Pomodoro.offset(0).first(100)],
pomodoro_collection_1 => [Pomodoro.offset(100).first(100)]
}
end
From app/views/pomodoro_cycles/show.html.erb
<% #pomodoros_collections.each do |collection| %>
<p><%= collection %></p>
<% end %>
However, this displays nothing in the browser.
app/models/pomodoro_cycle.rb
class PomodoroCycle < ApplicationRecord
has_many :pomodoros
end
app/models/pomodoro.rb
class Pomodoro < ApplicationRecord
belongs_to :pomodoro_cycle
end
Updated db/migrate/20180103032759_create_pomodoro_cycles.rb:
class CreatePomodoroCycles < ActiveRecord::Migration[5.1]
def change
create_table :pomodoro_cycles do |t|
t.string :activity
t.integer :iteration
t.integer :matrix_side_length
t.datetime :created_at
t.datetime :completed_at
t.string :category_labels, array:true, default: []
t.string :category_colors, array:true, default: []
t.string :username
t.timestamps
end
create table :pomodoros do |t|
t.belongs_to :pomodoro_cycle, index: true
t.datetime :completed_at
t.timestamps
end
add_index :pomodoros, :pomodoro_cycle_id
end
end
Untouched db/migrate/20180103054425_create_pomodoros.rb
class CreatePomodoros < ActiveRecord::Migration[5.1]
def change
create_table :pomodoros do |t|
t.boolean :status
t.string :category
t.string :color
t.datetime :completed_at
t.string :username
t.timestamps
end
end
end
First of all, as #SebastianPalma pointed out in the comments, the syntax is wrong
def pomodoro_collections
{
pomodoro_collection_0 => [Pomodoro.offset(0).first(100)],
pomodoro_collection_1 => [Pomodoro.offset(100).first(100)]
}
end
should be:
def pomodoro_collections
{
pomodoro_collection_0: [Pomodoro.offset(0).first(100)],
pomodoro_collection_1: [Pomodoro.offset(100).first(100)]
}
end
Make the keys in the hash symbols
Then to display each Pomodoro put something like:
<% #pomodoros_collections.each do |pomodoros_collection_hash| %>
<h2><%= pomodoros_collection_hash[0] %></h2>
<% pomodoros_collection_hash[1].each do |pomodoro| %>
<p><%= pomodoro.id %></p> #Or the attribute you want to display
<% end %>
<% end %>
Hope this help
I'm trying to debug a controller that just won't play ball. I've narrowed it down to the strong parameters not working properly and so I've tried it out on the rails console.
params = ActionController::Parameters.new({
"user"=> {
"login"=>"username",
"password"=>"[FILTERED]"
},
"staff_id"=>"1"
})
This returns, as you'd expect:
=> {"user"=>{"login"=>"username", "password"=>"[FILTERED]"}, "staff_id"=>"1"}
So, I attempted to filter the parameters, like so...
params.require(:staff_id)
=> "1"
> params.require(:user).permit(:password,:login)
=> {"password"=>"[FILTERED]", "login"=>"username"}
That looks ok.
In my controller, I have:
def create
#staff=Staff.find(params[:staff_id])
#user = #staff.create_user(reg_params[:user])
DISASTER
Now, at the point of the disaster, the user object #user should have a login and password set but It doesn't. I've tried logging the #user object at that point, it's properties are nil.
Why isn't my user object being created properly? If I remove the DISASTER, it creates a database record with blank fields, except for the timestamps.
Models:
class Staff < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_one :staff
end
Schema:
ActiveRecord::Schema.define(version: 20150909102012) do
create_table "staff", force: :cascade do |t|
t.string "qualifications"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
end
add_index "staff", ["users_id"], name: "index_staff_on_users_id"
create_table "users", force: :cascade do |t|
t.string "login"
t.string "username"
t.string "password"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
It routes to the custom controller ok. Here's the route:
Rails.application.routes.draw do
resources :staff do
resource :user, shallow: true, controller: 'staff_register'
end
resources :users
There's nothing else in the app because it's just an experiment to help me work on a bigger problem I've been struggling with.
Basically, I want to be able to link a staff model to a user model. I think I've done that ok, I just need help figuring out the strong parameters bit.
EDIT: here's the form for the nested resource:
<%= form_for #user, :url => staff_user_path(#staff) do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :login %><br>
<%= f.text_field :login %>
</div>
<div class="field">
<%= f.label :password %><br>
<%= f.text_field :password %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
In this line:
#user = #staff.create_user(reg_params[:user])
reg_params already gives you hash with all the permitted parameters:
{"password"=>"[FILTERED]", "login"=>"username"}
There is no user key there, hence reg_params[:user] is just nil. Instead you need to do:
#user = #staff.create_user(reg_params)
Now, you do not need to worry about staff_id here, as you are executing create_user method on already existing #staff model. This method will take care of the association.
I'm new to Ruby on Rails and have not programmed for many years. I'm trying some simple code that is similar to the sample provided in the "Getting Started with Rails" guide for Rails 3.2. Instead of Posts and Comments my models are States and Counties. I've reviewed the code for problems with pluralization, but don't see anything out of place. My system is configured with Rails 4.0 and ruby 1.9.3. I encounter the error after I list the states from the index page. Once the states are listed, I select to show a state, which should allow me to add a County, but instead I get the following error on the page:
uninitialized constant State::County
The code listed with the error is from /app/views/states/show.html.erb
</p>
<h2>Add a County:</h2>
<%= form_for([#state, #state.counties.build]) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
I'm providing other MVC files and the DB schema below.
Models:
state.rb
class State < ActiveRecord::Base
attr_accessible :abbr, :name
validates :abbr, :presence => true,
:length => { :maximum => 2 },
:format => { :with => /\A[A-Z]+\z/,
:message => "only 2 uppercase letters allowed" }
validates :name, :presence => true
has_many :counties, :dependent => :destroy
end
county.rb
class County < ActiveRecord::Base
attr_accessible :name, state_id
validates :name, :presence => true
belongs_to :state
end
Views
State/show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>Abbr:</strong>
<%= #state.abbr %>
</p>
<p>
<strong>Name:</strong>
<%= #state.name %>
</p>
<h2>Add a County:</h2>
<%= form_for([#state, #state.counties.build]) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<br />
<%= link_to 'Edit', edit_state_path(#state) %> |
<%= link_to 'Back', states_path %>
Routes.rb
resources :states do
resources :counties
end
Controllers
counties_controller.rb
class CountiesController < ApplicationController
def create
#state = State.find(params[:state_id])
#county = #state.counties.create(params[:county])
redirect_to state_path(#state)
end
def destroy
#state = State.find(params[:state_id])
#county = #state.counties.find(params[:id])
#county.destroy
redirect_to state_path(#state)
end
end
states_controller.rb
This is a standard file created by rails with the scaffold generator. No changes have been made to this file. If you need it to help with this issue I will post it, but it is rather long.
schema.rb
ActiveRecord::Schema.define(version: 20141013234441) do
create_table "counties", force: true do |t|
t.string "name"
t.integer "state_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "counties", ["state_id"], name: "index_counties_on_state_id", using: :btree
create_table "states", force: true do |t|
t.string "abbr", limit: 2, null: false
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
end
Any help is appreciated...
Never mind... I found the answer to my own question. I knew it had to be something simple. I was missing a colon in the county.rb file.
Original:
class County < ActiveRecord::Base
attr_accessible :name, state_id
Corrected:
class County < ActiveRecord::Base
attr_accessible :name, :state_id
I'm creating a very basic e-commerce app to teach myself rails and I've hit my first snag:
I created some associations so that merchants could assign categories to products they post and that works fine the way I've done it, however, the way it works now, when a merchant is creating a new product all the categories from the categories table are available to select. Hypothetically, if I wanted to limit that list to only categories that that specific merchant has created or been associated with, I presume taken from the categories_merchants table, how would I go about doing that?
I've shown the relevant tables and a form below to show what I've done but left out the models, however I have all the appropriate associations in them:
Products Table:
create_table :products do |t|
t.integer :merchant_id
t.string :title
t.text :body
t.date :publish_date
t.date :expiry_date
t.timestamps
Categories Table:
create_table :categories do |t|
t.string :name
t.timestamps
Categories_Products Table:
create_table :categories_products, :id =>false do |t|
t.integer :category_id
t.integer :product_id
end
add_index :categories_products, [:category_id, :product_id]
Categories_Merchants Table:
create_table :categories_merchants, :id =>false do |t|
t.integer :category_id
t.integer :merchant_id
end
add_index :categories_merchants, [:category_id, :merchant_id]
New Products form:
<%= simple_form_for(#product) do |f| %>
<div class="form-inputs">
<%= f.input :title %>
<%= f.input :body %>
<%= f.association :categories, :as => :collection_select %>
<%= f.input :publish_date %>
</div>
<% end %>
Thanks in advance ;)
You could do something like this:
<%= f.association :categories,
:as => :collection_select,
:collection => Category.includes(:categories_merchants).where("categories_merchants.merchant_id = ?", merchant_id) %>
Environment: Rails 3.0.1, MySQLI have a Users table, and I want to search for users by city.
I have the following code in users_controller:
def output
#results = User.select(:fname, :lname).where(['city = ?', params[:text1]]).all
output.html.erb in View:
<% #results.each do |r| %>
<%= #r.fname %>
<%= #r.lname %>
<% end %>
It will show up as undefined method `fname' for nil:NilClass.
However, if I type following in View, it works:
your search are <%= #results %>
The output is:
your search are [#<User fname: "adam", lname: "huang">, #<User fname: "eric", lname: "huang">]
The Users table is:
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.integer :uid
t.string :email
t.string :password
t.string :fname
t.string :lname
t.string :city
t.integer :pid
t.timestamps
end
end
Try this
<% #results.each do |r| %>
<%= r.fname %>
<%= r.lname %>
<% end %>
It looks like you did a simple typo.