Related
I am working on a react native application and as part of the project I am building an API using Ruby on Rails 5 in API Only mode with ActiveAdmin for the admin interface. I have everything setup, and it's all working well.
I was given the data in a file before having the idea of an API, the structure of which I need to replicate using rails, this is so it can be content manageable.
But I can't seem to get the active record associations correct.
This is a sample of the data file...
{
name: 'Scottish Stoics',
days: [
{
day: 'Monday',
meeting: [
{
name: 'Meeting one',
location: 'Test',
startTime: '11.00',
address: 'Test Street',
meetingLength: '1 Hour',
city: 'Edinburgh',
},
{
name: 'Meeting two',
location: 'Test',
startTime: '10.00',
address: 'Test Street',
meetingLength: '1 Hour',
city: 'Edinburgh',
},
{
name: 'Meeting three',
location: 'Test',
startTime: '10.00',
address: 'Test Street',
meetingLength: '1 Hour',
city: 'Edinburgh',
},
],
},
{
day: 'Tuesday',
meeting: [
{
name: 'Meeting one',
location: 'Test',
startTime: '10',
address: 'Test Street',
meetingLength: '1 Hour',
city: 'Edinburgh',
},
{
name: 'Meeting two',
location: 'Test',
startTime: '10',
address: 'Test Street',
meetingLength: '1 Hour',
city: 'Edinburgh',
},
{
name: 'Meeting three',
location: 'Test',
startTime: '10',
address: 'Test Street',
meetingLength: '1 Hour',
city: 'Edinburgh',
},
],
},
],
},
{
name: 'Scottish Cycling Group',
days: [
{
day: 'Sunday',
meeting: [
{
name: 'Meeting one',
location: 'Test',
startTime: '11.00',
address: 'Test Street',
meetingLength: '1 Hour',
city: 'Edinburgh',
},
{
name: 'Meeting two',
location: 'Test',
startTime: '10.00',
address: 'Test Street',
meetingLength: '1 Hour',
city: 'Edinburgh',
},
{
name: 'Meeting three',
location: 'Test',
startTime: '10.00',
address: 'Test Street',
meetingLength: '1 Hour',
city: 'Edinburgh',
},
],
},
{
day: 'Tuesday',
meeting: [
{
name: 'Meeting one',
location: 'Test',
startTime: '10.00',
address: 'Test Street',
meetingLength: '1 Hour',
city: 'Edinburgh',
},
{
name: 'Meeting two',
location: 'Test',
startTime: '10.00',
address: 'Test Street',
meetingLength: '1 Hour',
city: 'Edinburgh',
},
{
name: 'Meeting three',
location: 'Test',
startTime: '10.00',
address: 'Test Street',
meetingLength: '1 Hour',
city: 'Edinburgh',
},
],
},
],
}
I have a Group Model, Day Model and a Meeting Model.
Group
belongs_to :day
belongs_to :meeting
Meeting
has_many :groups
Day
has_many :groups
And I am getting this result.
[
{
id: 1,
name: "Scottish Stoics",
created_at: "2018-03-19T11:47:50.818Z",
updated_at: "2018-04-12T10:50:05.179Z",
day_id: 7,
meeting_id: 81
},
{
id: 2,
name: "Scottish Cycling Group",
created_at: "2018-03-19T11:47:57.498Z",
updated_at: "2018-04-11T22:13:26.656Z",
day_id: 7,
meeting_id: 83
},
]
Now I can use jbuilder to get the day name and meeting name which is fine, but what I can't do is select MULTIPLE meetings for one day, and MULTIPLE DAYS for the group. Is this data structure even going to be possible in Rails?
I can't work out if I should be using a different type of association, anyone able to shed some light on this for me?
Assuming that the top level nesting corresponds to Group you can form the associations like that:
Day
has_many :meetings
belongs_to :group
Meeting
belongs_to :day
Group
has_many :days
has_many :meetings, through: :days
Though i have the impression that in the JSON provided it should be meetings rather than meeting to keep it RESTful
While doing the seed.rb for my app I came across the following error when running rake db:seed:
rake aborted!
NameError: uninitialized constant Menu::CourseMenu
C:in `destroy_all'
C:.../db/seeds.rb:11:in `<top (required)>'
Tasks: TOP => db:seed
(See full trace by running task with --trace)
Menu:
class Menu < ActiveRecord::Base
belongs_to :user
has_many :course_menus, dependent: :destroy
end
CoursesMenu:
class CoursesMenu < ActiveRecord::Base
belongs_to :menu
has_and_belongs_to_many :recipes, dependent: :destroy
end
Seed.rb:
# This file should contain all the record creation needed to seed the database with its default values.
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
#
# Examples:
#
# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
# Mayor.create(name: 'Emanuel', city: cities.first)
User.destroy_all
Menu.destroy_all
CookBook.destroy_all
CoursesMenu.destroy_all
Recipe.destroy_all
User.create! [
{ email: "jean#mail.com", password: "12345", status: true },
{ email: "wendy#mail.com", password: "12345", status: true },
{ email: "jose#mail.com", password: "12345", status: true },
{ email: "vivi#mail.com", password: "12345", status: true },
{ email: "emilio#mail.com", password: "12345", status: true }
]
sample_menus = Menu.create! [
{ name: "For Mom", description: "Menu to lose weight" },
{ name: "For Dad", description: "Menu to gain more muscle" },
{ name: "For the lil tykes", description: "Menu so they stop being fat" },
{ name: "For the Vegan Aunt", description: "For the old harpy" }
]
sample_cookbooks = CookBook.create! [
{ name: "Jean'selections", description: "Premiun choices by Jean" },
{ name: "Wendy'selections", description: "Premiun choices by Wendy" },
{ name: "Jose'selections", description: "Premiun choices by Jose" },
{ name: "Best of All", description: "JPremiun choices by the Crew" }
]
sample_recipes = Recipe.create! [
{ img_url: "http://static.food2fork.com/BrownieFeature193f.jpg", title: "Slutty Brownies", source_url: "http://whatsgabycooking.com/slutty-brownies/"},
{ img_url: "http://static.food2fork.com/pizza292x2007a259a79.jpg", title: "Homemade Pizza", source_url: "http://www.simplyrecipes.com/recipes/homemade_pizza/" },
{ img_url: "http://static.food2fork.com/5337400468_d5892f3a03_od5cd.jpg", title: "Chicken Tortilla Soup", source_url: "http://thepioneerwoman.com/cooking/2011/01/chicken-tortilla-soup/"},
{ img_url: "http://static.food2fork.com/GuacamoleGrilledCheese6019.jpg", title: "Guacamole Grilled Cheese Sandwich", source_url: "http://www.twopeasandtheirpod.com/guacamole-grilled-cheese-sandwich/"}
]
sample_courses_menus = CoursesMenu.create! [
{ course_name: "Breakfast", day: "Monday" },
{ course_name: "Day Snack", day: "Monday" },
{ course_name: "Lunch", day: "Monday" },
{ course_name: "Dinner", day: "Monday" },
{ course_name: "Night Snack", day: "Monday" },
{ course_name: "Breakfast", day: "Tuesday" },
{ course_name: "Day Snack", day: "Tuesday" },
{ course_name: "Lunch", day: "Tuesday" },
{ course_name: "Dinner", day: "Tuesday" },
{ course_name: "Night Snack", day: "Tuesday" },
{ course_name: "Breakfast", day: "Wednesday" },
{ course_name: "Day Snack", day: "Wednesday" },
{ course_name: "Lunch", day: "Wednesday" },
{ course_name: "Dinner", day: "Wednesday" },
{ course_name: "Night Snack", day: "Wednesday" },
{ course_name: "Breakfast", day: "Thursday" },
{ course_name: "Day Snack", day: "Thursday" },
{ course_name: "Lunch", day: "Thursday" },
{ course_name: "Dinner", day: "Thursday" },
{ course_name: "Night Snack", day: "Thursday" },
{ course_name: "Breakfast", day: "Friday " },
{ course_name: "Day Snack", day: "Friday " },
{ course_name: "Lunch", day: "Friday " },
{ course_name: "Dinner", day: "Friday " },
{ course_name: "Night Snack", day: "Friday " },
{ course_name: "Breakfast", day: "Saturday" },
{ course_name: "Day Snack", day: "Saturday" },
{ course_name: "Lunch", day: "Saturday" },
{ course_name: "Dinner", day: "Saturday" },
{ course_name: "Night Snack", day: "Saturday" },
{ course_name: "Breakfast", day: "Sunday" },
{ course_name: "Day Snack", day: "Sunday" },
{ course_name: "Lunch", day: "Sunday" },
{ course_name: "Dinner", day: "Sunday" },
{ course_name: "Night Snack", day: "Sunday" }
]
sample_cookbooks. << 20.times { |index| CookBook.create! name: "CookBook#{index}", description: "This is a cookbook sample #{index}" }
CoursesMenu.all.each do |course_menu|
course_menu.recipes = sample_recipes.sample
course_menu.save!
end
Menu.all.each do |menu|
menu.course_menus = sample_courses_menus.sample
menu.save!
end
CookBook.all.each do |book|
book.recipes = sample_recipes.sample
book.save!
end
User.all.each do |user|
user.cook_books = sample_cookbooks.sample
user.menus = sample_menus.sample
user.save!
end
I suspect there is something I'm handling wrong with the relationship because if I change destroy_all to delete_all in the seed.rb this particular error doesn't occur.
I was hopping someone could point me in the right direction to solve this.
In your Menu model, change
has_many :course_menus, dependent: :destroy
to
has_many :courses_menus, dependent: :destroy
Would it be a more correct inflection to define the CoursesMenu as CourseMenu? If so your association would be correct as is.
Also, FYI, the reason destroy_all fails and delete_all works is because destroy_all deletes each record individually, executing callbacks (including dependent: :destroys) in the process. This is where the error occurs because Rails tries to use a model of type CourseMenu which doesn't exist the way you have defined your classes. In contrast, delete_all simply deletes the records in question, in one query (DELETE from menus), and does not try to execute any callback code, so Rails never encounters the mis-named resource.
Problem
Menu has many :course_menus
but your class is
CoursesMenu
Solution
You could just rename CoursesMenu to Course, and Menu would have many :courses.
Whatever you choose, you could check the names are correct :
:courses.to_s.capitalize.singularize
#=> "Course"
:course_menus.to_s.camelcase.singularize
#=> "CourseMenu"
i have a hash with array object :
{
false=>[#<Campaign id: 1, name: "campaign 1", active: false>, #<Campaign id: 3, name: "campaign 3", active: false>, #<Campaign id: 4, name: "campaign 4", active: false>],
true=>[#<Campaign id: 2, name: "campaign 2", active: true>]
}
how to convert above hash to hash
{
false=>[{id:1, name:"campaign 1"}, {id:3, name: "capaign 3"}, ....],
true =>[{id:2, name:"campaign 2"}]
}
hash.each {|k,v| hash[k] = v.map{|e| {id: e[:id], name: e[:name]}}}
and if you can use select_all method get the array of hash, not array of object, so you doesn't need to covert object to hash.
ModelName.connection.select_all("select id, name from <table_name>;")
=> [{id:xxx, name: xxx}.......]
Use attributes method on your object
attributes() public
Returns a hash of all the attributes with their names as keys and the values of the attributes as values.
hash = {
false => [#<Campaign id: 1, name: "campaign 1", active: false>, #<Campaign id: 3, name: "campaign 3", active: false>, #<Campaign id: 4, name: "campaign 4", active: false>],
true => [#<Campaign id: 2, name: "campaign 2", active: true>]
}
So this line should do the trick -
hash.each {|k, v| hash[k] = v.map(&:attributes) }
{
false => [{"id": 1, "name": "campaign 1", "active": false}, {"id": 3, "name": "campaign 3", "active": false}, {"id": 4, "name": "campaign 4", "active": false}],
true => [{"id": 2, "name": "campaign 2", "active": true}]
}
I am looking to group a list of projects by a nested field, in this case custom_field.value when a certain id is passed in.
[{
id: 1,
name: "project one ",
custom_fields: [
{
id: 4,
name: "Year",
value: "2010"
},
{
id: 5,
name: "Priority",
value: "low"
},
]},
{
id: 2,
name: "project two ",
custom_fields: [
{
id: 4,
name: "Year",
value: "2011"
},
{
id: 5,
name: "Priority",
value: "medium"
},
]},
{
id: 3,
name: "project three ",
custom_fields: [
{
id: 4,
name: "Year",
value: "2012"
},
{
id: 5,
name: "Priority",
value: "high"
},
]}]
So if the params[:id] == 4 I want the list to be ordered by the custom_field id's corresponding value in decending order.
So in this case they would be ordered.
2012
2011
2010
Any ideas?
Is this what you are looking for? Your question is a bit unclear but I think this should suffice:
Your Original Hash:
test = [{
id: 1,
name: "project one ",
custom_fields: [
{
id: 4,
name: "Year",
value: "2010"
},
{
id: 5,
name: "Priority",
value: "low"
},
]},
{
id: 2,
name: "project two ",
custom_fields: [
{
id: 4,
name: "Year",
value: "2011"
},
{
id: 5,
name: "Priority",
value: "medium"
},
]},
{
id: 3,
name: "project three ",
custom_fields: [
{
id: 4,
name: "Year",
value: "2012"
},
{
id: 5,
name: "Priority",
value: "high"
},
]}]
Use group_by and sort(with handling for elements where there is no id found):
def group_and_sort(test_hash,id)
test_hash.group_by do |g|
elem = g[:custom_fields].detect {|h| h[:id] == id}
elem ? elem[:value] : "0"
end.sort.reverse.to_h
end
Then call like:
group_and_sort(test,4)
#=>{"2012"=>
[{:id=>3,
:name=>"project three ",
:custom_fields=>
[{:id=>4, :name=>"Year", :value=>"2012"},
{:id=>5, :name=>"Priority", :value=>"high"}]}],
"2011"=>
[{:id=>2,
:name=>"project two ",
:custom_fields=>
[{:id=>4, :name=>"Year", :value=>"2011"},
{:id=>5, :name=>"Priority", :value=>"medium"}]}],
"2010"=>
[{:id=>1,
:name=>"project one ",
:custom_fields=>
[{:id=>4, :name=>"Year", :value=>"2010"},
{:id=>5, :name=>"Priority", :value=>"low"}]}]}
Assume projects is the data you pasted.
def order_values_by_id(pjs, id)
pjs.map{|p| p[:custom_fields].find{|f| f[:id] == id}[:value] }.sort.reverse
end
order_values_by_id(projects)
#=> ["2012", "2011", "2010"]
I'm starter in jqGrid, i write this code for Implement Grouping
$(function () {
var mydata = [
{ id: "11", invdate: "2007-10-01", name: "test", note: "note", amount: "200.00", tax: "10.00", total: "210.00" },
{ id: "12", invdate: "2007-10-02", name: "test2", note: "note2", amount: "300.00", tax: "20.00", total: "320.00" },
{ id: "13", invdate: "2007-09-01", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00" },
{ id: "14", invdate: "2007-10-04", name: "test", note: "note", amount: "200.00", tax: "10.00", total: "210.00" },
{ id: "15", invdate: "2007-10-05", name: "test2", note: "note2", amount: "300.00", tax: "20.00", total: "320.00" },
{ id: "16", invdate: "2007-09-06", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00" },
{ id: "17", invdate: "2007-10-04", name: "test", note: "note", amount: "200.00", tax: "10.00", total: "210.00" },
{ id: "18", invdate: "2007-10-03", name: "test2", note: "note2", amount: "300.00", tax: "20.00", total: "320.00" },
{ id: "19", invdate: "2007-09-01", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00" },
{ id: "21", invdate: "2007-10-01", name: "test", note: "note", amount: "200.00", tax: "10.00", total: "210.00" },
{ id: "22", invdate: "2007-10-02", name: "test2", note: "note2", amount: "300.00", tax: "20.00", total: "320.00" },
{ id: "23", invdate: "2007-09-01", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00" },
{ id: "24", invdate: "2007-10-04", name: "test", note: "note", amount: "200.00", tax: "10.00", total: "210.00" },
{ id: "25", invdate: "2007-10-05", name: "test2", note: "note2", amount: "300.00", tax: "20.00", total: "320.00" },
{ id: "26", invdate: "2007-09-06", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00" },
{ id: "27", invdate: "2007-10-04", name: "test", note: "note", amount: "200.00", tax: "10.00", total: "210.00" },
{ id: "28", invdate: "2007-10-03", name: "test2", note: "note2", amount: "300.00", tax: "20.00", total: "320.00" },
{ id: "29", invdate: "2007-09-01", name: "test3", note: "note3", amount: "400.00", tax: "30.00", total: "430.00"}];
jQuery("#list48").jqGrid({
data: mydata,
datatype: "local",
height: 'auto',
rowNum: 30,
rowList: [10, 20, 30],
colNames: ['Inv No', 'Date', 'Client', 'Amount', 'Tax', 'Total', 'Notes'],
colModel: [
{ name: 'id', index: 'id', width: 60, sorttype: "int" },
{ name: 'invdate', index: 'invdate', width: 90, sorttype: "date", formatter: "date" },
{ name: 'name', index: 'name', width: 100, editable: true },
{ name: 'amount', index: 'amount', width: 80, align: "right", sorttype: "float", formatter: "number", editable: true },
{ name: 'tax', index: 'tax', width: 80, align: "right", sorttype: "float", editable: true },
{ name: 'total', index: 'total', width: 80, align: "right", sorttype: "float" },
{ name: 'note', index: 'note', width: 150, sortable: false}],
pager: "#plist48",
viewrecords: true,
sortname: 'name',
grouping: true,
groupingView: { groupField: ['name'] },
caption: "Grouping Array Data" });
});
and create this grid
i want set Grouping Dynamicaly.Such that user Drag Header Column and Drop in top box after that grid Grop such this picture
please help me for implement this senaryo
. thanks all
On the jqGrid side you need to use groupingRemove and groupingGroupBy methods to change grouping dynamic, you can read more about them in documentation.
For the UI part you should look at following interactions:
Draggable
Droppable
Sortable
The Shopping Cart sample in Droppable should give you a very good overview on how to approach the subject.
Now after all that theoretical informations, I have created a sample on jsFiddle for you: jqGrid dynamic drag-n-drop grouping. It needs some styling to look exactly as what you are looking for, but it should allow you to understand all the internals. If you need some comments on the code let me know - I can add them later.