Writing each line from Textarea in a single document - ruby-on-rails

I want write mulitple lines from a textarea to a mongodb database:
First Line
Second Line
Third Line
etc.
Each line should be written in a single document.
So what I first figured out that I might use the gsub-function for separating the lines and after that I could write them with an each do - loop to the database.
And this point I got stuck.
Thanks in Advance for helping

Arthur's solution is correct if what you want is to put each line as sub-document of a single document.
If you really want multiple documents, then this may be the solution if it uses rails.
inputString=params["textareainput"]
lines=inputString.split("\n")
lines.each do |l|
Book.create(:content => l)
end
The code is placed in the controller (if you use MVC, probably in Rails framework)

So if you wanna have the lines split in your database, what would do, is something like this:
class Book
field :lines, type: Array
def text=(t)
doc = []
t.each_line { |l| dpc << l }
self.lines = doc
end
end

Related

Rails .where any field contains specific text

Is there a short-hand way of querying a Rails database for any record that has a field containing a specific piece of text? I know I could code every field with a .where("field_name LIKE ?", "my text"), but I have several fields and am wondering if there is a shorter way of doing this.
Thanks in advance.
I do not know of a framework-way to do so. You could code something using
my_attributes = YourModel.attributes
# delete attributes you do not need, like `id` etc.
# or just create an array with your desired attributes,
# whichever way is faster
queries = my_attributes.map { |attr| "#{attr} LIKE %insert_your_text_here%" }
# Do not use this if the text your looking for is provided by user input.
built_query = queries.join(" OR ")
YourModel.where(built_query)
This could bring you closer to your goal. Let me know if this makes sense to you.
edit: The answer https://stackoverflow.com/a/49458059/299781 mentions Ransack. That's a nice gem and takes the load off of you. Makes it easier, nicer and performs better :D
Glad you like this, but pay attention that you make your app open for sql injection, if you take user-input as the text you are looking for. (with this solution) Ransack would alleviate that.
class MyModel
scope :search_like, -> (field_name, search_string) {where("#{field_name} LIKE ?", "%#{search_string}%")}
end
then you can call it like:
MyModal.search_like('name', 'foobar')
UPDATE based on #holgar answer but beware if not indexed these searches can be slow on large data sets:
class MyModel
def self.multi_like(search_string)
my_attributes = [:first_name, :last_name] # probalby only use string fields here
queries = my_attributes.map { |attr| "#{attr} LIKE '%#{search_string}%'" }
where(queries.join(" OR "))
end
end
If you want full fledge text search based on params then you can use ransack gem

Rails: join an array with a new line between each component

I am trying to make an app in Rails 4.
I have this method:
def full_address
[self.first_line, middle_line, last_line, country_name].compact.join("\n")
end
When I try this, it prints a space between components.
I've read several posts on here that say that single quotation marks are the problem (I've also tried those). I also tried:
def full_address
[self.first_line, middle_line, last_line, country_name].compact.join("<br>")
end
When I try this, it prints 'br' between components.
How do I do this? I've seen responses in several other languages that talk about '+' signs being the solution. I've tried them, it doesnt work. I need help in rails please.
I'm trying to use this in my views show page as:
<%= #address.full_address %>
irb(main):004:0> puts ["a", "b", "c", "d"].join("\n")
a
b
c
d
You didn't show that part of the code but I suspect that the problem is that you're trying to put the result string in an HTML page. HTML ignores whitespace and that is why you don't get the newlines. You can try the solution you proposed with the <br> and try to add .html_safe

what is the best way to get a portion of this url

I am creating like a link like so:
<%= link_to('', "#{issueable}/#{order.id}/issues" %>
which creates a link like this:
root/version2/parts/2418/issues
I want to be able to get the "parts" (/version2/parts/2418/issues) portion of that url when the user clicks the link to that controller method.
You can use split:
link = "root/version2/parts/2418/issues"
puts link.split('/')[2].strip
#outputs parts
link = "version2/parts/2418"
puts link.split('/')[1].strip
#outputs parts
Ruby fiddle
In other words, you've got a string "/version2/parts/2418/issues" and you want to extract the 'parts' position from it.
"/version2/parts/2418/issues".split('/')[-3]
You'll need to figure out yourself whether to get [2] from the split array or [-3]. As an added '/' in the beginning or in the end could mess it up.
You could use regex assuming you know that it starts with "version2" and also know the order_id when it gets to it.
"/version2/parts/2418/issues".match(/\/version2\/(\w+)\/2418/)
puts $1

Simple recursive method

I have Board model. Board can be subscribed to other boards (as a feed).
Lets say I have board tree like this:
http://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Binary_tree.svg/200px-Binary_tree.svg.png
So:
Board.find(2).feeds are boards 5 and 7
Board.find(7).feeds are boards 2 and 6 etc.
I want to write method all_feeds which returns all feeds from all levels for certain board. For example:
Board.find(7).all_feeds would output array of boards with ids: 2,6,5,11
I started with something like:
def all_feeds
if feeds.empty?
return
else
feeds.each {|feed| feed.all_feeds}
return feeds
end
end
Probably have to add this return feeds to some global array, but not sure how should I do this.
Thanks for help.
ps. this is not always a binary tree, you can have more than 2 feeds.
I guess that what you want could be achieved with:
def all_feeds
unless feeds.empty?
feeds + feeds.map(&:all_feeds).flatten.compact
end
end
Array#flatten makes the result one-dimensional, while Array#compact removes the nil components.
For an explanation of the map(&:all_feeds) part, you can refer to this SO answer :)
Looks like it's working for below code:
def all_feeds
if feeds.empty?
self
else
[self]+feeds.map(&:all_feeds)
end
end
if it is allowed to use gems ancestry gem will help do the trick
Board.find(7).descendants
in this case it will be definitely one request to db without any recursion which is better for performance
you can implement ancestry idea without gem (or in top of it):
add ancestry field to your model
fill it correctly when you build your tree (for nested nodes with ids 2 and 6 it will be 2/7, with ids 5 and 11 - 2/7/6 )
and then just take it from db with like 2/% query

Rails way to offer modified attributes

The case is simple: I have markdown in my database, and want it parsed on output(*).
#post.body is mapped to the posts.body column in the database. Simple, default Activerecord ORM. That column stores the markdown text a user inserts.
Now, I see four ways to offer the markdown rendered version to my views:
First, in app/models/post.rb:
# ...
def body
markdown = RDiscount.new(body)
markdown.to_html
end
Allowing me to simply call #post.body and get an already rendered version. I do see lots of potential problems with that, e.g. on edit the textfield being pre-filled with the rendered HMTL instead of the markdown code.
Second option would be a new attribute in the form of a method
In app/models/post.rb:
# ...
def body_mardownified
markdown = RDiscount.new(body)
markdown.to_html
end
Seems cleanest to me.
Or, third in a helper in app/helpers/application_helper.rb
def markdownify(string)
markdown = RDiscount.new(string)
markdown.to_html
end
Which is used in the view, instead of <%= body %>, <%= mardownify(body) %>.
The fourth way, would be to parse this in the PostsController.
def index
#posts = Post.find(:all)
#posts.each do |p|
p.body = RDiscount.new(string).to_html
#rendered_posts << p
end
end
I am not too familiar with Rails 3 proper method and attribute architecture. How should I go with this? Is there a fifth option? Should I be aware of gotchas, pitfalls or performance issues with one or another of these options?
(*) In future, potentially updated with a database caching layer, or even special columns for rendered versions. But that is beyond the point, merely pointing out, so to avoid discussion on filter-on-output versus filter-on-input :).
The first option you've described won't work as-is. It will cause an infinite loop because when you call RDiscount.new(body) it will use the body method you've just defined to pass into RDiscount (which in turn will call itself again, and again, and so on). If you want to do it this way, you'd need to use RDiscount.new(read_attribute('body')) instead.
Apart from this fact, I think the first option would be confusing for someone new looking at your app as it would not be instantly clear when they see in your view #post.body that this is in fact a modified version of the body.
Personally, I'd go for the second or third options. If you're going to provide it from the model, having a method which describes what it's doing to the body will make it very obvious to anyone else what is going on. If the html version of body will only ever be used in views or mailers (which would be logical), I'd argue that it makes more sense to have the logic in a helper as it seems like the more logical place to have a method that outputs html.
Do not put it in the controller as in your fourth idea, it's really not the right place for it.
Yet another way would be extending the String class with a to_markdown method. This has the benefit of working on any string anywhere in your application
class String
def to_markdown
RDiscount.new(self)
end
end
#post.body.to_markdown
normal bold italic
If you were using HAML, for example in app/views/posts/show.html.haml
:markdown
= #post.body
http://haml-lang.com/docs/yardoc/file.HAML_REFERENCE.html#markdown-filter
How about a reader for body that accepts a parse_with parameter?
def body(parse_with=nil)
b = read_attribute('body')
case parse_with
when :markdown then RDiscount.new(b)
when :escape then CGI.escape(b)
else b
end
end
This way, a regular call to body will function as it used to, and you can pass a parameter to specify what to render with:
#post.body
normal **bold** *italic*
#post.body(:markdown)
normal bold italic

Resources