I'm trying to implement this pattern
class A
Mongoid::Document
belongs_to :price
def price
self[:price] || calculate_price
end
def calculate_price
#Some logic
end
end
meaning that a user can either force a price to A or get a calculated price. Trouble is, the setter doesn't work as expected:
2.0.0-rc2 :013 > a = A.new
=> #<A _id: 5215b3321d41c89a1f000001, price_id: nil>
2.0.0-rc2 :015 > a.price = Price.new
=> #<Price _id: 5215b3451d41c89a1f000002, i(inclusive_tax): nil, e(exclusive_tax): nil, tax_id: nil>
2.0.0-rc2 :016 > a.price
=> "5215b3451d41c89a1f000002"
What is the way to override the setter so things work as expected?
I tried to add a
def price=(val)
super(val)
end
but there is no super for the setter.
Any hint?
What about this work around?
class A
Mongoid::Document
belongs_to :price
def price
Price.find(self[:price]) || calculate_price
end
def calculate_price
#Some logic
end
end
Related
How to query search an Array with where? What's the correct way?
U have an association like this:
# Foo has many bars
Foo.first.bars
Controller:
def index
#bars = []
#datas = Foo.where(email: current_user.email)
#datas.map { |d| #bars.push(d.bar).where("name like ?", "%#{params[:email]}%") }
respond_to do |format|
format.html
format.json { render json: #bars }
end
end
Instead of where for Array, what is the correct query term?
You can use the select method to filter out values in an array given a certain condition.
[1,2,3,4,5].select { |num| num.even? } #=> [2, 4]
Or for your particular example:
#bars = #datas.map { |d| d.bars }.select { |b| b.name.include? params[:email] }
However, since you actually don't have an array of bars and would have to create it, this is simply an unnecessary step and a more straightforward solution would be:
#datas = Foo.where(email: current_user.email)
# #bars is an array
#bars = #datas.map { |d| d.bars.where("name like ?", "%#{params[:email]}%") }
or
# #bars is an ActiveRecord object
#bars = Bar.where(id: #datas.pluck(:id)).where("name like ?", "%#{params[:email]}%")
I recently tried adding an Array type column in my Rails app which uses Postgres 9.3. I followed some online tutorials and added the following code into my project.
Migration
add_column :matches, :p1_characters, :string, array: true, default: []
add_column :matches, :p2_characters, :string, array: true, default: []
Now if I try to manually update a match's characters in the console like so:
> m = Match.first
> m.p1_characters = ["1","2","3"]
> m.save
# Works fine!
Everything saves correctly in the database as expected.
The problem lies in trying to update the p1_characters/p2_characters attributes in my rails app.
p1_edit_character_.html.erb
<%= simple_form_for(#match, method: :patch,
:url => p1_set_character_match_path(#match)) do |f| %>
# displays a form of check boxes where the user can select multiple characters.
<h1>Select P1 Character</h1>
<%= f.input :p1_characters, label: "Player 1 Character", as: :check_boxes,
collection: #characters %>
<%= f.button :submit, "Select Character", class: "btn-lg btn-primary" %>
<% end %>
I know that the params being passed to my controller is:
"match"=>{"p1_characters"=>["1", "2", "3", ""]}
The error I get is
undefined method `gsub' for 1:Fixnum
Below is my controller with the relevant methods and strong params
matches_controller.rb
def p1_edit_character
#match = Match.find(params[:id])
#characters = Game.find(#match.game_id).characters
end
def p1_set_character
#match = Match.find(params[:id])
if #match.update_attributes(match_params)
if #match.p1_characters != []
flash[:notice] = "P1 character set."
end
redirect_to matches_path
end
end
private
def match_params
params.require(:match).permit(:p1_score, :p2_score, :match_date,
:p1_accepted, :p2_accepted, {p1_characters: []}, {p2_characters: []},
:disputed, :finalized_date)
end
Please, any guidance would be so helpful.
Thanks.
I have a model 'Index' as:
class Index
include Mongoid::Document
belongs_to :project
end
Another model PercentileRankIndex inherits Index
class PercentileRankIndex < Index
def self.model_name
Index.model_name
end
end
Suppose I do :
p = Index.first (OR EVEN) p = PercentileRankIndex.first
I get this :
#<PercentileRankIndex _id: 51630ece34b2613d27000011, project_id: "51630ece34b2613d27000010", enabled: true, _type: "PercentileRankIndex", :enabled: "true">
However on doing
p.project
=>nil
The belongs_to relationship isnt working on child class. Why? How can I fix it?
I'm having some problems using mongoid-3.0.6 with polymorphic fields.
Using rails 3.2.8 and ruby 1.9.3
Using a normal polymorphic relation:
class Shirt
include Mongoid::Document
field :name, localize: true
belongs_to :itemizable, polymorphic: true
end
class Item
include Mongoid::Document
field :price, type: Float
field :quantity, type: Integer, :default => 1
has_one :product, as: :itemizable
accepts_nested_attributes_for :product
end
The same association is available through the metadata:
>> Item.reflect_on_association(:product)
#<Mongoid::Relations::Metadata
autobuild: false,
class_name: Product,
cyclic: nil,
dependent: nil,
inverse_of: nil,
key: _id,
macro: has_one,
name: product,
order: nil,
polymorphic: true,
relation: Mongoid::Relations::Referenced::One,
setter: product=,
versioned: false>
>> item = Item.new
#<Item _id: 50606c1668ce87692e000003, _type: nil, created_at: nil, updated_at: nil, deleted_at: nil, price: nil, quantity: 1>
but when i run
>> item.product = Shirt.new or >> item.build_product
i got always the same error
NameError: uninitialized constant Product
Full stack error
Any thoughts?
Thanks in advance.
Solved
Found the motive
Need to add the class_name to the relation
has_one :product, as: :itemizable, class_name: "Toy"
class Account
include Mongoid::Document
include Geocoder::Model::Mongoid
geocoded_by :zip
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
before_validation :pass_confirm
after_validation :geocode_check
before_create :assign_subs
field :email, type: String
field :type, type: String
field :zip, type: String
field :oldzip, type: String
field :coordinates, type: Array
field :latitude, type: Float
field :longitude, type: Float
auto_increment :num, collection: :account_nums
index :num, unique: true
has_many :submissions
mount_uploader :photo, PhotoUploader
def self.find_by_num(num)
Account.where(num: num).first
end
protected
def pass_confirm
self.password_confirmation ||= self.password
end
def geocode_check
if self.oldzip != self.zip
self.oldzip = self.zip
self.geocode
end
end
def assign_subs
binding.pry
Submission.where(email: self.email).each do |sub|
sub.zip = self.zip
self.submissions << sub
end
end
end
--
class Submission
include Mongoid::Document
include Mongoid::Search
include Mongoid::Timestamps::Created
include Geocoder::Model::Mongoid
geocoded_by :zip
before_validation :fix_rate
after_validation :geocode
search_in :message, tags: :name
field :email, type: String
field :rate, type: String
field :message, type: String
field :type, type: String
field :zip, type: String
field :coordinates, type: Array
field :latitude, type: Float
field :longitude, type: Float
auto_increment :num, collection: :submission_nums
index :num, unique: true
has_and_belongs_to_many :tags
belongs_to :account
mount_uploader :photo, PhotoUploader
protected
def fix_rate
self.rate = self.rate.sub(/[^\d]*/, '').sub(/(\d*).*/, '\1')
end
end
--
pry(#<Account>)> self.submissions << Submission.first
=> [#<Submission _id: 4e751df86066252059000054, _type: nil, created_at: 2011-09-17 22:23:52 UTC, _keywords: ["tfnwuaty"], email: "krisbltn#gmail.com", rate: "49", message: "tfnwuaty", type: "person", zip: nil, coordinates: nil, latitude: nil, longitude: nil, num: 1, tag_ids: [], account_id: BSON::ObjectId('4e751e0d6066252059000059'), photo: "lawrence.jpg">]
pry(#<Account>)> self.submissions
=> []
as you see above, when trying to add a child document it doesn't get saved. Any ideas as to what could be going on?
Also- this is a has_many / belongs_to relationship, and when I change it to has_and_belongs_to_many it seems to work fine.
My guess is that you've upgraded Mongoid, but haven't read the upgrading docs.
Add , :autosave => true to Account's relation with Submission.
class Account
include Mongoid::Document
has_many :submissions, :autosave => true
end
class Submission
include Mongoid::Document
belongs_to :account
end
Account.delete_all
Submission.delete_all
Submission.create
account = Account.new
account.submissions << Submission.first
account.save
Submission.first.account == account
This was also submitted as a GitHub issue. Tsk tsk.