Limiting :association results accessible on a form in my rails app - ruby-on-rails

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) %>

Related

Can't see nested fields in view when using accepts_nested_attributes_for method while using Ruby 2.3, Rails 5.0, Windows (32-bit)

I'm trying to build a workout application where you submit a workout that consists of several exercises in rails. I was trying to create a "new" workout view where you can submit a new workout along with nested exercises but my "new" view is only showing the workout form fields, but not the exercise form fields. Btw I'm using Ruby 2.3 and Rails 5.0. Can anyone see what I'm doing wrong?
Workout Model (workout.rb)
class Workout < ActiveRecord::Base
has_many :exercises, :dependent => :destroy
accepts_nested_attributes_for :exercises
end
Exercise Model (exercise.rb)
class Exercise < ActiveRecord::Base
belongs_to :workout
end
Workouts Controller (workouts_controller.rb)
class WorkoutsController < ApplicationController
def new
#workout = Workout.new
#workout.exercises.build
end
end
New Workout View (views\workouts\new.html.erb)
<h1>Create New Workout</h1>
<%= form_for(#workout) do |f| %>
<%= f.number_field :workout_length, :placeholder => "Workout length (minutes)" %> <br>
<%= f.text_field :workout_description, :placeholder => "Workout description" %> <br>
<% f.fields_for :exercises do |builder| %>
<p>
<%= builder.text_field :exercise_description %>
</p>
<% end %>
<%= f.submit "SUBMIT WORKOUT" %>
Schema (schema.rb)
ActiveRecord::Schema.define(version: 20161207040053) do
create_table "exercises", force: :cascade do |t|
t.string "exercise_description"
t.integer "workout_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["workout_id"], name: "index_exercises_on_workout_id"
end
create_table "workouts", force: :cascade do |t|
t.integer "workout_length"
t.string "workout_description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
I figured it out... I didn't set up the proper relationship between the exercise and workout model.

How to manage nested relation in RoR?

I'm new to Rails and trying to create an C2C marketplace App just to understand how rails works and start some real project later on.
The idea is that User can place Order to other User. Orders is related with user's Printer (you choice user where you want to print on /order page). Printer in its turn have many colors to print
For now, Im stack with very basic things.
I want to display list of all printers with owner's name and colors available on /order page in Orders controller. Thank you in advance for any ideas how I can do this
class User < ActiveRecord::Base
has_many :printers, dependent: :destroy
has_many :orders, dependent: :destroy
end
class Order < ActiveRecord::Base
belongs_to :user
validates :user_id, presence: true
end
class Printer < ActiveRecord::Base
belongs_to :user
validates :user_id, presence: true
validates :model, presence: true, allow_nil: true
has_many :materials, dependent: :destroy
end
Orders controller with index action (/orders)
class OrdersController < ApplicationController
def index
#printers = Printer.all
end
end
And index.html.erb
<% #printers.each do |p| %>
<div class="col-xs-9">
<div><%= "USERNAME HERE" %></div> <!--Do not know how to display parent's model here? -->
<div><%= p.model %></div> <!--Works fine-->
<div><%= p.colors.each do |c| c.color end %></div> <!--Display array instead of strings-->
</div>
<div class="col-xs-3">
<button>Order</button>
</div>
<% end %>
Simplified schema.db
ActiveRecord::Schema.define(version: 20160627132435) do
create_table "colors", force: :cascade do |t|
t.string "color"
t.integer "printer_id"
end
create_table "orders", force: :cascade do |t|
t.string "price"
t.string "status"
t.integer "user_id"
end
create_table "printers", force: :cascade do |t|
t.string "model"
t.integer "user_id"
end
add_index "printers", ["user_id"], name: "index_printers_on_user_id", using: :btree
create_table "users", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
end
add_foreign_key "orders", "users"
add_foreign_key "printers", "users"
end
I think you should be able to do:
<% #printers.each do |p| %>
<div class="col-xs-9">
<div><%= p.user.first_name %></div> <!--Do not know how to display parent's model here? -->
<div><%= p.model %></div> <!--Works fine-->
<div><% p.colors.each do |c|
<%= c.color %>
<% end %></div> <!--Display array instead of strings-->
</div>
<div class="col-xs-3">
<button>Order</button>
</div>
<% end %>

Model structure in many to many relationship

I have two models Students and Colleges for which I want to be able to list the college's a student has applied for and also the list of students applying for a college.
I have this form that creates a Student and also selects colleges through the checkbox
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h3>Add Students</h3>
<%= simple_form_for #student do |f| %>
<%= f.input :name %>
<%= f.input :sex, collection: ["Male", "Female"] %>
<%= f.input :age, collection: 15..100 %>
<%= f.input :dob %>
<%= f.input :current_school %>
<%= f.input :current_level %>
<%= f.input :country, priority: [ "Singapore" ] %>
<%= f.input :sat_score %>
<%= f.input :applied_colleges, collection: College.all,group_method: :id, as: :check_boxes %> <%= f.input :current_mentor, collection: Mentor.all, group_method: :name, as: :select %>
<%= f.button :submit %>
<% end %>
</div>
This is the schema for the app:
ActiveRecord::Schema.define(version: 20150131123428) do
create_table "colleges", force: true do |t|
t.string "name"
t.string "country"
t.integer "sat_min_score"
t.integer "sat_max_score"
t.integer "tution_fees"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "student_list"
end
create_table "mentors", force: true do |t|
t.string "name"
t.string "sex"
t.integer "age"
t.date "dob"
t.text "bio"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "students", force: true do |t|
t.string "name"
t.string "sex"
t.integer "age"
t.date "dob"
t.string "current_school"
t.string "current_level"
t.string "country"
t.integer "sat_score"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "current_mentor_id"
t.string "applied_colleges"
t.string "current_mentor"
end
add_index "students", ["current_mentor_id"], name: "index_students_on_current_mentor_id"
end
This is the student model
class Student < ActiveRecord::Base
serialize :applied_colleges, Array
has_one :mentor
validates :name, presence: true, length: { maximum:50 }
validates :age, presence: true, numericality: { lesser_than_or_equal_to: 120, only_integer: true}
validates :sat_score, presence: true, numericality: {lesser_than_or_equal_to: 1600, only_integer: true}
def self.college_id_to_college_name(applied_colleges)
colleges = []
applied_colleges.each do |var|
colleges << var.to_i
end
#college_list = []
colleges.each do |var|
#college_list << College.find_by(id:var)
end
#college_list.delete_at(#college_list.length-1)
#college_list
end
def self.save_applied_student_id_to_student_joined_column_for_college(student_id,college_list)
college_list.each do |college|
college.student_list << student_id
end
end
end
This is the College model
class College < ActiveRecord::Base
validates :name, presence:true, length: { maximum:50 }
validates :sat_min_score, presence:true, numericality: {lesser_than: 2400, only_integer: true}
validates :sat_max_score, presence:true, numericality: {lesser_than_or_equal_to: 2400, only_integer: true}
end
I am very confused with the modelling between student and college The model needs to be such that each student object has the list of colleges he has applied to and each college has the list of students who has applied.
Currently what I am doing for saving the list of colleges a student has applied to by saving the id of the colleges from the colleges chosen through the checkbox in the form and saving it in a column.
I am thinking to insert the student id of every student in the column called student_list. But this seems like a bad way.
I want to model Students and Colleges in such a way that each student object has the list of colleges he has applied to and each college object has the list of students who has applied.
How do I model this? What would be the necessary migration required?
If you want to have a good way to join students and colleges, I'd make a Model called Application [beware, this might be a reserved word, so you may need a different name for the model -- don't recall off the top of my head] (needs a student_id, and a college_id). Student has_many Applications, has_many Colleges through Applications. Reverse for Colleges, has_many applications, has_many students through applications. Application belongs_to student, and belongs_to college.
Though at this point, you're mixing the traditional definitions of students and applicants. Generally, people might be applicants, and applicants might be enrolled students.

Rails associations in a form

I am trying to figure out how to register certain values to their respective table using the form, check the order form to better understand which values need to be registering to which table.
I have also displayed the table entries, models and controller related to this question. If someone can guide me to where I can obtain further understanding on coding the associations in forms that would be great.
order form
<%= simple_form_for(#order) do |f| %>
<%= f.association :items, collection: Item.all, label_method: :name, value_method: :id %>
<%= [need to display the price of the item selected] %>
<%= f.input :quantity ???? [need to register in the order_items table] %>
<%= [register sub total to orders table] %>
<%= f.submit %>
<% end %>
tables
create_table "order_items", force: true do |t|
t.integer "item_id"
t.integer "order_id"
t.integer "quantity"
end
create_table "orders", force: true do |t|
t.integer "user_id"
t.integer "client_id"
t.boolean "status"
t.decimal "sub_total"
end
create_table "items", force: true do |t|
t.string "name"
t.decimal "price"
t.integer "stock"
end
models
class Order < ActiveRecord::Base
...
has_many :order_items
has_many :items, :through => :order_items
end
class Item < ActiveRecord::Base
...
has_many :order_items
has_many :orders, :through => :order_items
end
class OrderItem < ActiveRecord::Base
belongs_to :item
belongs_to :order
end
orders controller
def create
#order = Order.new(order_params)
#order.user_id = current_user.id
#order.status = TRUE
end
def order_params
params.require(:order).permit(:code, :client_id, :user_id, :memo, :status, item_ids: [])
end

Ruby Rails update two different table columns using form

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

Resources