How to create seeds.rb array? - ruby-on-rails

I'd like to populate the Department table using the seeds.rb file. I've created only two columns in the table. There are three more created by rails (id, created_at, updated_at).
When I run rake db:seed, I get the following error:
ArgumentError: wrong number of arguments (3 for 0..1)
Here's what the seeds.rb file looks like:
departments = Department.create([{ depttitle: 'dept 1' }, { deptdescription: 'this is the first dept' }],
[{ depttitle: 'dept 2' }, { deptdescription: 'this is the second dept' }],
[{ depttitle: 'dept 3' }, { deptdescription: 'this is the third dept' }])
Is the issue with how I've created the array or something else?

The reason it didn't work is that you actually passed three arrays with two hashes in each of them.
Pass a single array to the #create method with a single hash for each record you want to create.
For example:
Department.create([{ deptitle: 'dept 1', deptdescription: 'this is the first dept' },
{ depttitle: 'dept 2', deptdescription: 'this is the second dept' }])
But instead of 'creating an array' you could use a simple loop to create Department records.
10.times do |x|
Department.create({deptitle: "dept #{x}", deptdescription: "this is the #{x} department"})
end
In my opinion it looks cleaner, takes less place and it is easier to change number of seed records if you need to.
To create a numeral from a number (for "this is the Xst dept" sentence) you could use a humanize gem.

The way we do it is as follows:
departments = [
{depttitle: "Title", deptdescription: "description"},
{depttitle: "Title2", deptdescription: "description2"},
{depttitle: "Title3", deptdesctiption: "description3"}
]
You can then loop through them like this:
departments.each do |department|
Department.create department
end
#Sebastian Brych's answer is right though - you're passing arrays for each new record when you should pass a single array with multiple hashes.

You can create your records separately as shown below.
Department.create(depttitle: 'dept 1' , deptdescription: 'this is the first dept')
Department.create(depttitle: 'dept 2' , deptdescription: 'this is the second dept')

Related

Rspec, how to expect to receive with only a subset of key value pair?

I have a spec that expects a class to receive a method with some arguments. I only want to check for a subset of key/value pair from the arguement hash :
it 'calls Stripe::Checkout::Session#create with the correct line items' do
expect(Stripe::Checkout::Session).to receive(:create).with({
line_items: [{
price: "bla",
quantity: 1
}],
}
)
subject
end
here I only want to check that line_items is present in the argument hash with the correct value.
However the actual hash received has more values and I get the following error :
#<Stripe::Checkout::Session (class)> received :create with unexpected arguments
expected: ({:line_items=>[{:price=>"bla", :quantity=>1}]}, *(any args))
got: ({:allow_promotion_codes=>true, :automatic_tax=>{:enabled=>true}, :billing_address_collection=>"requir...vh.me/fr/thank-you?checkout_session_id={CHECKOUT_SESSION_ID}", :tax_id_collection=>{:enabled=>true}}, {:stripe_account=>"bla"})
How can I tell rspec to only check for the presence of a subset of key/value pair ?
You want hash_including, which matches subsets of hashes:
...to receive(:create).with(hash_including(
line_items: [{
price: "bla",
quantity: 1
}],
)
See the docs: https://relishapp.com/rspec/rspec-mocks/v/3-2/docs/setting-constraints/matching-arguments

Update value of array field using mongoid

I'm trying to find a way to update a single array item using mongoid. I'm using Rails 4 and Mongodb.
My model looks like this
class User
include Mongoid::Document
include Mongoid::Timestamps
field :my_book_list, type: Array, default: []
field :book_name, type: String
I'm able to add entry to the array field using the following code:
User.where(id: self.user_id).add_to_set("my_book_list" => self.book_name)
After I have added data to the array, in the database it looks like this
db.collection.users
{
"_id" : ObjectId("56e09d54a0d00b0528000001"),
"status" : true,
"sign_in_count" : 3,
"my_book_list" :
["Learning Ruby", "MongoDB for Dummies"]
}
What I'm struggling with is to find a Rails / Mongoid way of updating the value of an item in the array by looking for the name.
Simply put, how do I change the value of my_book_list[1] by searching for it through name and not knowing its index. In this case index 1 is "MongoDB for Dummies" and needs to be updated to "MongoDB". So that the "my_book_list" array field looks like this after its updated:
db.collection.users
{
"_id" : ObjectId("56e09d54a0d00b0528000001"),
"status" : true,
"sign_in_count" : 3,
"my_book_list" :
["Learning Ruby", "MongoDB"]
}
How do I achieve this ?
Instead of updating, think of it as adding & removing. You can use pull (https://docs.mongodb.org/ecosystem/tutorial/mongoid-persistence/#atomic)
Where your add to set uniquely adds it to an array, pull removes it based on the name. So assuming this:
user = User.find_by(id: self.user_id)
user.add_to_set(my_book_list: 'First Story')
p user.my_book_list
=> ['First Story']
user.add_to_set(my_book_list: 'Second Story')
p user.my_book_list
=> ['First Story', 'Second Story']
user.add_to_set(my_book_list: 'Third Story')
p user.my_book_list
=> ['First Story', 'Second Story', 'Third Story']
user.pull(my_book_list: 'Second Story')
p user.my_book_list
=> ['First Story', 'Third Story']
If you had duplicates in the set you can use pull_all, but you are using add to set so you won't need to.
This was more of a conceptual problem being a ruby beginner. The answer lies that mongo arrays are simple ruby array and we can use standard ruby methods to update the array.
In this case in my rails console I did this and it worked. The second line finds the array item and replaces with the new wird,
u = User.first
u.my_book_list.map! { |x| x == "MongoDB for Dummies" ? "MongoDB": x}
u.save

Show values from helper method in drop down

I am using a hash constant in my ROR application. I want to show the names from the hash constant to drop down.
helper.rb
PRODUCE_GROWING_METHODS = [
{id: 1, name: 'Conventional'},
{id: 2, name: 'Organic'},
]
def produce_growing_methods
PRODUCE_GROWING_METHODS
end
_produce.haml
= f.simple_fields_for :produce_details do |pd|
= pd.input :produce_growing_method, :collection => produce_growing_methods.collect { |x| [x[0], x[1]] }, :prompt => "Select Growing Method"
I tried as shown above in _produce.haml but i am getting the empty drop down. Names from the constant are not populated in drop down.
Can any one help me how to show the names from the PRODUCE_GROWING_METHODS hash constant to a drop down.
Thanks
You should map the hash by keys. In your case the keys are :id and :name:
produce_growing_methods.map { |x| [x[:id], x[:name]] }
In reality you are always better of using a generic solution rather then manual mapping.
Here is a better way of achieving the same, but it will work as well for array of thousand hashes:
ary = [
{id: 1, name: 'Conventional'},
{id: 2, name: 'Organic'},
]
ary.map(&:values)
#=> [[1, "Conventional"], [2, "Organic"]]

Rails - Nested includes on Active Records?

I have a list of events that I fetch.
I'm trying to include every user associated to this event and every profile associated to each user. The Users get included but not their profiles.
How Would i do this
Event.includes(:users [{profile:}])
The docs don't seem to be clear:
http://guides.rubyonrails.org/active_record_querying.html
I believe the following should work for you.
Event.includes(users: :profile)
If you want to include an association (we'll call it C) of an already included association (we'll call it B), you'd use the syntax above. However, if you'd like to include D as well, which is also an association of B, that's when you'd use the array as given in the example in the Rails Guide.
A.includes(bees: [
:cees,
:dees
])
You could continue to nest includes like that (if you actually need to). Say that A is also associated with Z, and that C is associated to E and F.
A.includes({
bees: [{
cees: [:ees, :effs]
}, :dees]
}, :zees)
And for good fun, we'll also say that E is associated to J and X, and that D is associated to Y.
A.includes({
bees: [{
cees: [{
ees: [:jays, :exes]
}, :effs]
},
{
dees: :wise
}
]
}, :zees)
Please refer to Joe Kennedy's solution.
Here's a more readable example (for future me).
includes(
:product,
:package, {
campaign: [
:external_records,
{ account: [:external_records] },
{ agency: [:external_records] },
:owner,
:partner,
]
}
)
If anyone is doing a respond_to block to generate nested json, you can do something like:
respond_to do |f|
f.json do
render json: event.to_json(include: {users: {include: :profile} }), status: :ok
end
end

Retrieving specific fixtures in Rails

I have a YML file containing fixtures for a Rails model (Comment) which looks like this (pardon the formatting):
comment_a:
id: 1
text: 'foo'
visible: false
comment_b:
id: 2
text: 'bar'
visible: true
comment_c:
id: 3
text: 'baz'
visible: true
I know that I can select an individual Comment fixture like so:
comments(:comment_a)
In one of my acceptance tests, I want to find all the Comments which have visible = true. How do I select a set of Comments that meet certain criteria so I can iterate over them afterwards?
You need made the request by your ActiveRecord Object. Comments.all(:conditions => {:visible => true})

Resources