So after a merge, my RoR 3 project no longer does 'creates' correctly. Default attributes get set correctly, but not the ones I pass in:
1.9.3-p125 :020 > f=Ifilter.create(:name => "test2", :regex => "()" )
SQL (101.5ms) INSERT INTO "ifilters" ("created_at", "name", "regex", "updated_at") VALUES (?, ?, ?, ?) [["created_at", Sat, 10 Mar 2012 03:36:24 UTC +00:00], ["name", nil], ["regex", nil], ["updated_at", Sat, 10 Mar 2012 03:36:24 UTC +00:00]]
=> #<Ifilter id: 2, name: nil, regex: nil, created_at: "2012-03-10 03:36:24", updated_at: "2012-03-10 03:36:24">
However, save still works:
1.9.3-p125 :021 > f=Ifilter.new
=> #<Ifilter id: nil, name: nil, regex: nil, created_at: nil, updated_at: nil>
1.9.3-p125 :022 > f.name = "test"
=> "test"
1.9.3-p125 :023 > f.regex = "()"
=> "()"
1.9.3-p125 :024 > f.save
SQL (4.8ms) INSERT INTO "ifilters" ("created_at", "name", "regex", "updated_at") VALUES (?, ?, ?, ?) [["created_at", Sat, 10 Mar 2012 04:13:10 UTC +00:00], ["name", "test"], ["regex", "()"], ["updated_at", Sat, 10 Mar 2012 04:13:10 UTC +00:00]]
=> true
What's going on?
Thanks!
Looks like you may have attr_accessible on your model. http://api.rubyonrails.org/classes/ActiveModel/MassAssignmentSecurity/ClassMethods.html#method-i-attr_accessible
If you are using it, attributes that aren't explicitly listed won't get set via #new, #create, and #update_attributes (and a few more).
This usually happens when you have attribute whitelisting enabled. Make sure you define the attributes that are settable via mass-assignment in your model via the attr_accessible macro:
class Ifilter
attr_accessible :name, :regex
...
end
Related
I have a application that allows a user to upload a creative and assign it to multiple weeks
Week Model
class Week < ActiveRecord::Base
has_many :creative_weeks
has_many :creatives, :through => :creative_weeks
end
Creative Model
class Creative < ActiveRecord::Base
has_many :creative_weeks
has_many :weeks, :through => :creative_weeks
mount_uploader :image, CreativeUploader
end
Creative Weeks [Join Table]
class CreativeWeek < ActiveRecord::Base
belongs_to :week
belongs_to :creative
end
I know the association works which allows me to issue a creative to multiple weeks based on my console:
2.0.0p353 :020 > c = Creative.first
Creative Load (0.2ms) SELECT "creatives".* FROM "creatives" ORDER BY "creatives"."id" ASC LIMIT 1
=> #<Creative id: 10, name: "", account_id: 1, week_id: nil, campaign_id: 1, image: "Quakes_2013_DigiOOH_40YR_704x496.jpg", created_at: "2014-02-20 18:13:47", u
pdated_at: "2014-02-20 18:13:47">
2.0.0p353 :021 > c.week_ids
(0.2ms) SELECT "weeks".id FROM "weeks" INNER JOIN "creative_weeks" ON "weeks"."id" = "creative_weeks"."week_id" WHERE "creative_weeks"."creative_id" = ? [["
creative_id", 10]]
=> [3]
2.0.0p353 :022 > c.week_ids = [1, 2, 3]
Week Load (0.2ms) SELECT "weeks".* FROM "weeks" WHERE "weeks"."id" IN (1, 2, 3)
Week Load (0.1ms) SELECT "weeks".* FROM "weeks" INNER JOIN "creative_weeks" ON "weeks"."id" = "creative_weeks"."week_id" WHERE "creative_weeks"."creative_id"
= ? [["creative_id", 10]]
(0.1ms) begin transaction
SQL (0.3ms) INSERT INTO "creative_weeks" ("created_at", "creative_id", "updated_at", "week_id") VALUES (?, ?, ?, ?) [["created_at", Thu, 20 Feb 2014 18:20:27
UTC +00:00], ["creative_id", 10], ["updated_at", Thu, 20 Feb 2014 18:20:27 UTC +00:00], ["week_id", 1]]
SQL (0.1ms) INSERT INTO "creative_weeks" ("created_at", "creative_id", "updated_at", "week_id") VALUES (?, ?, ?, ?) [["created_at", Thu, 20 Feb 2014 18:20:27
UTC +00:00], ["creative_id", 10], ["updated_at", Thu, 20 Feb 2014 18:20:27 UTC +00:00], ["week_id", 2]]
(1.0ms) commit transaction
=> [1, 2, 3]
2.0.0p353 :023 >
The issue I am having is getting this same functionality to work on the front end. It will only pass in one value, typically the last one chosen
In my form:
<div class="field">
<%= f.collection_select(:week_ids, Week.all, :id, :start_at, {}, multiple: true, name: 'creative[week_ids]') %>
</div>
Can anyone advise me what I am missing?
TIA
Change the select tag's name to this:
name: 'creative[week_ids][]'
That extra '[]' at the end of the name specifies that you want an array of values to be posted.
Using strong parameters you have to specify that the value will be an array:
def your_strong_params
params.require(:creative).permit(week_ids: [])
end
Model
class Pm < ActiveRecord::Base
attr_accessor :name
end
Console
me = Pm.new
#=> <Pm id: nil, name: nil, created_at: nil, updated_at: nil>
me.name = "Josh"
#=> "Josh"
me.save
#=>(0.4ms) BEGIN
#=> true
#=> SQL (0.8ms) INSERT INTO "pms" ("created_at", "name", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["created_at", Sat, 01 Jun 2013 19:02:27 UTC +00:00], ["name", nil], ["updated_at", Sat, 01 Jun 2013 19:02:27 UTC +00:00]]
#=>(1.3ms) COMMIT
me
#=> <Pm id: 4, name: nil, created_at: "2013-06-01 19:02:27", updated_at: "2013-06-01 19:02:27">
I have a model with a name attribute and an attr_accessor defined. The record saves but it doesn't update the name attribute. Am I missing something simple here?
If your Pmp model ("Pimp"? "Pump"? "Pimple"?) has a DB field called "name", there's no reason to use attr_accessor :name. With attr_accessor :name, ActiveRecord's dynamically generated attribute methods will never be invoked, and yes, it means the attribute won't be saved to the database.
This question already has an answer here:
Adding a JOIN between two tables
(1 answer)
Closed 9 years ago.
My Organization class looks something like this:
has_many Students
My Student class looks like this:
has_many Klasses
belongs_to Organization
My Klass class looks like this:
some field named : price
scope :top_expensive_classes, joins(:students).order('price DESC')
belongs_to Student
And my query looks like this:
#results = Klass.top_expensive_classes.where(organization_id: params[:id]).limit(RESULT_SET_COUNT)
Notice that it starts with Klass, so that's the problem because I am searching in the where class for organization_id but that is not in the Klass, it is in Student class , so somehow I should introduce a join somewhere to fix this but couldn't figure it out.
I think the real issue is your associations are likely incorrect.
A student has many classes
A class has many students
but what you have is
A student has many classes
A class belongs to a single student
This doesn't really make sense (at least in any situation I've ever seen a class and student interact). You should be creating a many-to-many relationship instead of a one-to-many relationship between Klass and Student.
class Student < ActiveRecord::Base
has_many :klasses, through: :student_klasses
has_many :student_klasses
end
class Klass < ActiveRecord::Base
has_many :students, through: :student_klasses
has_many :student_klasses
end
class StudentKlass < ActiveRecord::Base
belongs_to :student
belongs_to :klass
end
Once you have these correct associations in place, you need to call .joins on the :students association from the Klass class. You can do without the scope.
Klass.joins(:students).where("students.organization_id = ?", params[:id]).order('price DESC').limit(RESULT_SET_COUNT)
Read the guide on ActiveRecord Querying.
Here is the proof (using the exact model definitions above) that the ordering of the associations does not matter.
irb(main):001:0> s = Student.create(name: "Deefour")
SQL (3.6ms) INSERT INTO "students" ("created_at", "name", "updated_at") VALUES (?, ?, ?) [["created_at", Fri, 08 Mar 2013 01:33:32 UTC +00:00], ["name", "Deefour"], ["updated_at", Fri, 08 Mar 2013 01:33:32 UTC +00:00]]
=> #<Student id: 1, name: "Deefour", created_at: "2013-03-08 01:33:32", updated_at: "2013-03-08 01:33:32">
irb(main):002:0> kk = []
=> []
irb(main):003:0> kk << Klass.create(title: "Klass 1")
SQL (0.3ms) INSERT INTO "klasses" ("created_at", "title", "updated_at") VALUES (?, ?, ?) [["created_at", Fri, 08 Mar 2013 01:34:06 UTC +00:00], ["title", "Klass 1"], ["updated_at", Fri, 08 Mar 2013 01:34:06 UTC +00:00]]
=> [#<Klass id: 1, title: "Klass 1", created_at: "2013-03-08 01:34:06", updated_at: "2013-03-08 01:34:06">]
irb(main):004:0> kk << Klass.create(title: "Klass 2")
SQL (0.3ms) INSERT INTO "klasses" ("created_at", "title", "updated_at") VALUES (?, ?, ?) [["created_at", Fri, 08 Mar 2013 01:34:14 UTC +00:00], ["title", "Klass 2"], ["updated_at", Fri, 08 Mar 2013 01:34:14 UTC +00:00]]
=> [#<Klass id: 1, title: "Klass 1", created_at: "2013-03-08 01:34:06", updated_at: "2013-03-08 01:34:06">, #<Klass id: 2, title: "Klass 2", created_at: "2013-03-08 01:34:14", updated_at: "2013-03-08 01:34:14">]
irb(main):005:0> s.klasses = kk
Klass Load (0.1ms) SELECT "klasses".* FROM "klasses" INNER JOIN "student_klasses" ON "klasses"."id" = "student_klasses"."klass_id" WHERE "student_klasses"."student_id" = ? [["student_id", 1]]
SQL (0.4ms) INSERT INTO "student_klasses" ("created_at", "klass_id", "student_id", "updated_at") VALUES (?, ?, ?, ?) [["created_at", Fri, 08 Mar 2013 01:34:29 UTC +00:00], ["klass_id", 1], ["student_id", 1], ["updated_at", Fri, 08 Mar 2013 01:34:29 UTC +00:00]]
SQL (0.1ms) INSERT INTO "student_klasses" ("created_at", "klass_id", "student_id", "updated_at") VALUES (?, ?, ?, ?) [["created_at", Fri, 08 Mar 2013 01:34:29 UTC +00:00], ["klass_id", 2], ["student_id", 1], ["updated_at", Fri, 08 Mar 2013 01:34:29 UTC +00:00]]
=> [#<Klass id: 1, title: "Klass 1", created_at: "2013-03-08 01:34:06", updated_at: "2013-03-08 01:34:06">, #<Klass id: 2, title: "Klass 2", created_at: "2013-03-08 01:34:14", updated_at: "2013-03-08 01:34:14">]
irb(main):006:0> Student.first.klasses.map(&:id)
Student Load (0.2ms) SELECT "students".* FROM "students" ORDER BY "students"."id" ASC LIMIT 1
Klass Load (0.1ms) SELECT "klasses".* FROM "klasses" INNER JOIN "student_klasses" ON "klasses"."id" = "student_klasses"."klass_id" WHERE "student_klasses"."student_id" = ? [["student_id", 1]]
=> [1, 2]
I am trying to generate some seed material.
seed_array.each do |seed|
Task.create(date: Date.new(2012,06,seed[1]), start_t: Time.new(2012,6,2,seed[2],seed[3]), end_t: Time.new(2012,6,2,seed[2] + 2,seed[3]), title: "#{seed[0]}")
end
Ultimately I will put random hours, minutes, seconds. The problem that I am facing is that instead of creating a time with the 2012-06-02 date it creates a time with a different date: 2000-01-01.
I tested Time.new(2012,6,2,2,20,45) in rails console and it works as expected. When I am trying to seed my database however some voodoo magic happens and I don't get the date I want.
Any inputs are appreciated. Thank you!
Update1:
(0.0ms) begin transaction SQL
(0.5ms) INSERT INTO "tasks" ("created_at", "date", "description",
"end_t", "group_id", "start_t", "title", "updated_at") VALUES (?, ?,
?, ?, ?, ?, ?, ?) [["created_at", Tue, 03 Jul 2012 02:15:34 UTC
+00:00], ["date", Thu, 07 Jun 2012], ["description", nil],
["end_t", 2012-06-02 10:02:00 -0400], ["group_id", nil],
["start_t", 2012-06-02 08:02:00 -0400], ["title", "99"],
["updated_at", Tue, 03 Jul 2012 02:15:34 UTC +00:00]]
(2.3ms) commit transaction
This is a small sample of the log.
Update 2
Task id: 101, date: "2012-06-26", start_t: "2000-01-01 08:45:00", end_t: "2000-01-01 10:45:00", title: "1", description: nil, group_id: nil, created_at: "2012-07-03 02:15:33", updated_at: "2012-07-03 02:15:33"
This is what shows up in rails console.
Sounds like you used the :time type for your start_t and end_t. In that context time refers to a pure time of day data type, with no date, because that's what the SQL time type is.
Ruby's Time type covers both date and time, so your database column needs to be :datetime. In fact ruby has no pure time of day class so activerecord uses a regular Time with a bogus date instead.
I have tested you code like this:
arr = [1,2,3]
arr.each do |seed|
Timetest.create(time: Time.new(2012,6,2,2,20,45), title: "#{seed}")
end
And its working as expected. But i got this sql on my console and its a bit different than yours in your start_t and end_t
SQL (4.1ms) INSERT INTO "timetests" ("created_at", "time", "title", "updated_at") VALUES (?, ?, ?, ?) [["created_at", Tue, 03 Jul 2012 02:11:35 UTC +00:00], ["time", Sat, 02 Jun 2012 07:20:45 UTC +00:00], ["title", "1"], ["updated_at", Tue, 03 Jul 2012 02:11:35 UTC +00:00]]
Update 1
Have you tried to use DateTime.new instead of Time.new?
Task.create(date: DateTime.new(2012,06,seed[1]), start_t: DateTime.new(2012,6,2,seed[2],seed[3]), end_t: DateTime.new(2012,6,2,seed[2] + 2,seed[3]), title: "#{seed[0]}")
I initialize an AdUnit object au with
au = AdUnit.new( cp )
where cp is equal to:
{:name=>"second56", :description=>nil, :target_window=>"BLANK", :explicitly_targeted=>false, :ad_unit_sizes_attributes=>[{:height=>90, :width=>728, :is_aspect_ratio=>false, :environment_type=>"BROWSER"}], :dfp_id=>"22319511", :parent_id_dfp=>"22261791"}
and the resulting object au is
#<AdUnit id: nil, dfp_id: "22319511", parent_id_dfp: "22261791", parent_id_bulk: nil, name: "second56", description: nil, target_window: "BLANK", explicitly_targeted: false, created_at: nil, updated_at: nil>
At this point, au.valid? and au.new_record? both return true.
If I do au.save (or au.save! for that matter) the result is nil and nothing is saved to the database. but if I do
aud = au.dup
aud.save
the result is true and the record is saved.
I can save my object with the duplicate workaround, but this looks really weird to me. can anybody give any ideas as to why is this happening? Below the SQL fragments from the 2 save statements from Rails console.
Thanks in advance all Rails gurus.
Returning nil and not saving:
SQL (1.0ms) INSERT INTO "ad_units" ("created_at", "description", "dfp_id", "explicitly_targeted", "name", "parent_id_bulk", "parent_id_dfp", "target_window", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) [["created_at", Wed, 04 Jan 2012 17:28:37 UTC +00:00], ["description", nil], ["dfp_id", "22400631"], ["explicitly_targeted", false], ["name", "zapiFirstLevel366"], ["parent_id_bulk", nil], ["parent_id_dfp", "1166751"], ["target_window", "BLANK"], ["updated_at", Wed, 04 Jan 2012 17:28:37 UTC +00:00]]
=> nil
Returning true and saving:
SQL (0.9ms) INSERT INTO "ad_units" ("created_at", "description", "dfp_id", "explicitly_targeted", "name", "parent_id_bulk", "parent_id_dfp", "target_window", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) [["created_at", Wed, 04 Jan 2012 17:29:58 UTC +00:00], ["description", nil], ["dfp_id", "22400631"], ["explicitly_targeted", false], ["name", "zapiFirstLevel366"], ["parent_id_bulk", nil], ["parent_id_dfp", "1166751"], ["target_window", "BLANK"], ["updated_at", Wed, 04 Jan 2012 17:29:58 UTC +00:00]]
=> true
OK, this was caused by the usage of accepts_nested_attributes_for when AdUnit has a has_and_belongs_to_many relationship with AdUnitSize. So I got to learn that these 2 do not work together nicely.
The only thing is, it might be good to have a warning somewhere, instead of having to find out about it from .save returning nil on a valid? = true object instead of true or false.
Using save! raises an exception if the record is invalid. It doesn't return anything.
If you need a return value use only save.
Basically if save! didn't raise, the record is saved successfuly. If you don't see it, then you're probably loading it wrong.